From db42baa33e726a46cff00fde8687bcf4045e5432 Mon Sep 17 00:00:00 2001 From: Saeed Asgari Date: Mon, 22 Jun 2026 15:55:41 +0330 Subject: [PATCH] add dbgate and mssql --- README.md | 4 + SUMMARY.md | 41 ++++++++++- dbgate/README.md | 135 ++++++++++++++++++++++++++++++++++ dbgate/docker-compose.yml | 19 +++++ docs/AI_CONTEXT.md | 26 +++++-- docs/backups.md | 69 ++++++++++++++--- docs/decisions.md | 48 ++++++++++++ docs/domains.md | 32 ++++++++ docs/secrets.md | 32 ++++++++ docs/security.md | 7 +- docs/server.md | 33 ++++++++- docs/services.md | 64 ++++++++++++++++ mssql/README.md | 117 +++++++++++++++++++++++++++++ mssql/docker-compose.yml | 19 +++++ nginx-proxy-manager/README.md | 2 + postgres/README.md | 4 +- 16 files changed, 632 insertions(+), 20 deletions(-) create mode 100644 dbgate/README.md create mode 100644 dbgate/docker-compose.yml create mode 100644 mssql/README.md create mode 100644 mssql/docker-compose.yml diff --git a/README.md b/README.md index eeacb44..c0e77be 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ SilverLinux is the primary self-hosted platform for Silver Solutions and hosts s ### Running * PostgreSQL +* Microsoft SQL Server 2022 Express * Gitea * OpenProject * Jitsi Meet @@ -32,6 +33,7 @@ SilverLinux is the primary self-hosted platform for Silver Solutions and hosts s * Nginx Proxy Manager * BaGet * Gitea Actions Runner +* DbGate ### Planned @@ -66,9 +68,11 @@ Secrets are stored outside the repository: ```text baget/ +dbgate/ docs/ gitea/ jitsi/ +mssql/ nginx-proxy-manager/ openproject/ portainer/ diff --git a/SUMMARY.md b/SUMMARY.md index 738d410..30f5cad 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -1,6 +1,6 @@ # SilverLinux Infrastructure Summary -Last Updated: 2026-06-21 +Last Updated: 2026-06-22 ## Overview @@ -19,6 +19,7 @@ The platform hosts source control, project management, video conferencing, conta | Portainer | https://portainer.silveressence.net | | Jitsi Meet | https://meet.silveressence.net | | BaGet | https://nuget.silveressence.net | +| DbGate | https://dbgate.silveressence.net | --- @@ -91,6 +92,24 @@ Purpose: --- +### Microsoft SQL Server Express + +Purpose: + +* Support projects requiring Microsoft SQL Server +* Provide a private SQL Server 2022 Express platform + +Access: + +* Docker `internal` network only +* Port 1433 is not publicly exposed + +Status: + +* Operational + +--- + ### Portainer Purpose: @@ -139,6 +158,24 @@ Status: --- +### DbGate + +Purpose: + +* Browser-based MSSQL and PostgreSQL administration + +Access: + +* https://dbgate.silveressence.net +* HTTPS through Nginx Proxy Manager +* Username and password required + +Status: + +* Operational + +--- + ## Shared Infrastructure ### Docker @@ -166,7 +203,9 @@ Contains: * SMTP credentials * PostgreSQL passwords +* MSSQL SA password * OpenProject secrets +* Future DbGate password * Future OAuth secrets This file must never be committed to Git. diff --git a/dbgate/README.md b/dbgate/README.md new file mode 100644 index 0000000..1bb655e --- /dev/null +++ b/dbgate/README.md @@ -0,0 +1,135 @@ +# DbGate + +## Overview + +DbGate is the HTTPS-accessible database administration portal for SilverLinux. + +URL: + +```text +https://dbgate.silveressence.net +``` + +Status: + +```text +Operational +``` + +It administers private Microsoft SQL Server and PostgreSQL instances without exposing either database server directly to the internet. + +--- + +## Service Information + +| Property | Value | +| --- | --- | +| Container | `dbgate` | +| Image | `dbgate/dbgate:latest` | +| Application port | `3000` | +| Networks | `internal`, `proxy` | +| Compose location | `/srv/docker/dbgate/docker-compose.yml` | +| Data location | `/srv/docker/dbgate/data` | + +The `internal` network provides database access. The `proxy` network connects DbGate to Nginx Proxy Manager. + +--- + +## Reverse Proxy + +| Setting | Value | +| --- | --- | +| Domain | `dbgate.silveressence.net` | +| Scheme | `http` | +| Forward host | `dbgate` | +| Forward port | `3000` | +| SSL | Let's Encrypt | +| Force SSL | Enabled | +| HTTP/2 | Enabled | + +Only DbGate is publicly accessible. MSSQL port `1433` and PostgreSQL port `5432` remain private. + +--- + +## Authentication + +DbGate requires a username and password before granting access. The initial unauthenticated deployment was corrected by configuring `LOGIN` and `PASSWORD`. + +The running server currently stores the DbGate credentials directly in its Compose configuration. The repository intentionally does not contain the password; its Compose definition resolves `DBGATE_PASSWORD` from the deployment environment. + +Planned improvement: + +* Add `DBGATE_PASSWORD` to `/srv/secrets/company.env`. +* Deploy with `docker compose --env-file /srv/secrets/company.env up -d`. +* Remove the credential from the server-side Compose file. + +--- + +## Database Connections + +### SilverLinux MSSQL + +| Setting | Value | +| --- | --- | +| Engine | SQL Server | +| Server | `mssql` | +| Port | `1433` | +| Default database | `master` | +| User | `sa` | +| Encrypt | Yes | +| Trust server certificate | Yes | + +The connection was validated against `master`, `model`, `msdb` and `tempdb`. + +PostgreSQL is also reachable through the shared `internal` network using hostname `postgres` and port `5432`. + +--- + +## Validation + +```bash +docker ps +docker logs dbgate +``` + +Expected log message: + +```text +DbGate API listening on port 3000 +``` + +--- + +## Architecture + +```text +Internet + -> Nginx Proxy Manager + -> DbGate + -> MSSQL 2022 Express + -> PostgreSQL 17 +``` + +--- + +## Backup Requirements + +Back up: + +```text +/srv/docker/dbgate/data +``` + +Also retain the Compose definition, Nginx Proxy Manager configuration and DbGate credential through the centralized secrets backup after migration. + +--- + +## Related Documentation + +* mssql/README.md +* postgres/README.md +* nginx-proxy-manager/README.md +* docs/domains.md +* docs/security.md +* docs/secrets.md +* docs/backups.md diff --git a/dbgate/docker-compose.yml b/dbgate/docker-compose.yml new file mode 100644 index 0000000..ab5d102 --- /dev/null +++ b/dbgate/docker-compose.yml @@ -0,0 +1,19 @@ +services: + dbgate: + image: dbgate/dbgate:latest + container_name: dbgate + restart: unless-stopped + environment: + LOGIN: admin + PASSWORD: ${DBGATE_PASSWORD} + volumes: + - /srv/docker/dbgate/data:/root/.dbgate + networks: + - internal + - proxy + +networks: + internal: + external: true + proxy: + external: true diff --git a/docs/AI_CONTEXT.md b/docs/AI_CONTEXT.md index 3fefb1a..87a9b6a 100644 --- a/docs/AI_CONTEXT.md +++ b/docs/AI_CONTEXT.md @@ -19,6 +19,7 @@ Public IP: 51.255.83.140 ## Core Services * PostgreSQL +* Microsoft SQL Server 2022 Express * Gitea * OpenProject * Jitsi Meet @@ -26,6 +27,7 @@ Public IP: 51.255.83.140 * Nginx Proxy Manager * BaGet * Gitea Actions Runner (`silverlinux-runner`) +* DbGate ## Domains @@ -39,6 +41,8 @@ portainer.silveressence.net -> Portainer nuget.silveressence.net -> BaGet (through Nginx Proxy Manager) +dbgate.silveressence.net -> DbGate (through Nginx Proxy Manager) + ## Secrets Secrets are stored in: @@ -54,10 +58,19 @@ Always use env_file. proxy internal +MSSQL is attached only to `internal`. DbGate is attached to both `internal` and `proxy`. + ## Authentication Gitea: +* Local accounts +* OpenID disabled +* Google OAuth planned +* GitHub OAuth planned + +OpenProject: + * Local accounts ## CI/CD @@ -69,13 +82,14 @@ The global self-hosted runner is operational at `/srv/docker/gitea-runner` with Silver 2.0 uses `.gitea/workflows/package.yml` to publish NuGet packages to BaGet when a push to `net-8-version` has a commit message containing `[Package]`. The runner registration token is stored in `/srv/secrets/company.env`. The BaGet publishing key is stored as the repository Actions secret `BAGET_API_KEY`. -* OpenID disabled -* Google OAuth planned -* GitHub OAuth planned -OpenProject: +## Databases -* Local accounts +PostgreSQL 17 and Microsoft SQL Server 2022 Express are operational. + +MSSQL uses hostname `mssql` on the `internal` Docker network. Port 1433 is not published. + +DbGate provides authenticated HTTPS administration for MSSQL and PostgreSQL at `https://dbgate.silveressence.net`. ## Documentation @@ -94,3 +108,5 @@ and the README.md of each service folder before making infrastructure recommenda * PostgreSQL selected as shared database platform * BaGet deployed at nuget.silveressence.net through Nginx Proxy Manager * Gitea Actions and a global self-hosted runner selected for package publishing +* MSSQL Express deployed alongside PostgreSQL +* DbGate selected as the database administration portal diff --git a/docs/backups.md b/docs/backups.md index 5e084bd..ec968da 100644 --- a/docs/backups.md +++ b/docs/backups.md @@ -28,6 +28,28 @@ Critical --- +#### Microsoft SQL Server + +Data location: + +```text +/srv/docker/mssql/data +``` + +Required: + +* Native SQL Server database backups +* MSSQL Compose configuration +* `MSSQL_SA_PASSWORD` from the shared secrets backup + +Importance: + +Critical + +Do not rely on copying live database files as the only backup method. + +--- + #### Gitea Data Location: @@ -81,7 +103,9 @@ Contains: * SMTP credentials * PostgreSQL passwords +* MSSQL SA password * OpenProject secrets +* Future DbGate password * Future OAuth secrets Importance: @@ -196,6 +220,27 @@ Medium --- +#### DbGate Data + +Location: + +```text +/srv/docker/dbgate/data +``` + +Contains: + +* Saved connections +* DbGate application state + +Also retain the Nginx Proxy Manager route and DbGate authentication credential. + +Importance: + +Medium + +--- + ## Backup Storage Current Location: @@ -247,15 +292,17 @@ Keep: Restore order: -1. PostgreSQL -2. Shared secrets -3. Nginx Proxy Manager -4. Gitea -5. OpenProject -6. Portainer -7. Jitsi -8. BaGet -9. Gitea Actions Runner +1. Shared secrets +2. PostgreSQL +3. Microsoft SQL Server +4. Nginx Proxy Manager +5. Gitea +6. OpenProject +7. Portainer +8. Jitsi +9. BaGet +10. Gitea Actions Runner +11. DbGate --- @@ -289,7 +336,7 @@ data directories. ### Step 4 -Restore PostgreSQL databases. +Restore PostgreSQL and Microsoft SQL Server databases. ### Step 5 @@ -314,3 +361,5 @@ Verify: * postgres/README.md * gitea/README.md * openproject/README.md +* mssql/README.md +* dbgate/README.md diff --git a/docs/decisions.md b/docs/decisions.md index 51b2407..86b2709 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -274,6 +274,54 @@ when additional services begin consuming the same secret management approach. --- +## 2026-06-22 - Deploy Microsoft SQL Server Express Alongside PostgreSQL + +Decision: + +* Run Microsoft SQL Server 2022 Express alongside PostgreSQL. +* Attach MSSQL only to the `internal` Docker network. +* Do not publish port `1433` or route MSSQL through the reverse proxy. +* Store `MSSQL_SA_PASSWORD` in `/srv/secrets/company.env`. + +Reason: + +* Support Silver projects that require Microsoft SQL Server compatibility. +* Allow both database platforms to coexist without exposing database ports. + +Status: + +```text +Implemented +``` + +--- + +## 2026-06-22 - Select DbGate for Database Administration + +Decision: + +* Use DbGate to administer Microsoft SQL Server and PostgreSQL. +* Connect DbGate to both the `internal` and `proxy` Docker networks. +* Publish only the DbGate web interface through Nginx Proxy Manager. +* Require DbGate authentication and HTTPS. + +Reason: + +* Provides one lightweight, modern browser interface for both database platforms. +* Keeps PostgreSQL and MSSQL private. + +Follow-up: + +Move the DbGate password from the server-side Compose configuration to `/srv/secrets/company.env`. + +Status: + +```text +Implemented +``` + +--- + ## Future Decisions Document future decisions using the following template: diff --git a/docs/domains.md b/docs/domains.md index f7446f1..2224e2c 100644 --- a/docs/domains.md +++ b/docs/domains.md @@ -145,6 +145,38 @@ Active --- +### DbGate + +Domain: + +```text +dbgate.silveressence.net +``` + +Purpose: + +* HTTPS database administration portal + +Container: + +```text +dbgate +``` + +Routing: + +```text +Nginx Proxy Manager -> dbgate:3000 +``` + +Status: + +```text +Active +``` + +--- + ## DNS DNS records should point to: diff --git a/docs/secrets.md b/docs/secrets.md index 4039117..694b952 100644 --- a/docs/secrets.md +++ b/docs/secrets.md @@ -67,6 +67,19 @@ Used by: --- +### Microsoft SQL Server + +```text +MSSQL_SA_PASSWORD +``` + +Used by: + +* Microsoft SQL Server 2022 Express +* DbGate's MSSQL connection + +--- + ### OpenProject ```text @@ -132,6 +145,25 @@ Future use: --- +### DbGate Credential Migration + +The running DbGate deployment currently has its login credential in the server-side Compose configuration. Move the password to: + +```text +/srv/secrets/company.env +DBGATE_PASSWORD +``` + +The repository Compose definition already references `DBGATE_PASSWORD` and contains no real password. + +Status: + +```text +Migration pending +``` + +--- + ## Rules * Never commit secrets to Git. diff --git a/docs/security.md b/docs/security.md index 382128d..1a4ef10 100644 --- a/docs/security.md +++ b/docs/security.md @@ -72,6 +72,7 @@ Examples: * SMTP credentials * PostgreSQL passwords +* MSSQL SA password * OpenProject secrets * Future OAuth secrets @@ -169,11 +170,13 @@ Priority: ## Database Security -PostgreSQL is not exposed publicly. +PostgreSQL and Microsoft SQL Server are not exposed publicly. Database access is restricted to Docker internal networks. -Applications communicate with PostgreSQL through the internal Docker network. +Applications and DbGate communicate with the database containers through the `internal` Docker network. + +DbGate is the public administration entry point and must require authentication and HTTPS. Its web interface is routed through Nginx Proxy Manager; database ports `5432` and `1433` remain private. --- diff --git a/docs/server.md b/docs/server.md index a4a865f..f9aacf4 100644 --- a/docs/server.md +++ b/docs/server.md @@ -50,7 +50,13 @@ Purpose: Purpose: -* Shared database platform +* Primary PostgreSQL database platform + +### Microsoft SQL Server Express + +Purpose: + +* Private SQL Server platform for compatible applications ### Fail2Ban @@ -93,6 +99,7 @@ Examples: * OpenProject * Jitsi Meet * Portainer +* DbGate --- @@ -106,6 +113,8 @@ Examples: * Nginx Proxy Manager * BaGet * Gitea Actions Runner +* Microsoft SQL Server 2022 Express +* DbGate --- @@ -128,6 +137,8 @@ Contains: /srv/docker/nginx-proxy-manager /srv/docker/baget /srv/docker/gitea-runner +/srv/docker/mssql +/srv/docker/dbgate ``` --- @@ -143,6 +154,8 @@ Contains: * SMTP credentials * Database passwords * Application secrets +* MSSQL SA password +* Future DbGate password * Future OAuth credentials --- @@ -189,6 +202,22 @@ Suggested structure: --- +### Microsoft SQL Server Express + +```text +/srv/docker/mssql/data +``` + +--- + +### DbGate + +```text +/srv/docker/dbgate/data +``` + +--- + ### Nginx Proxy Manager ```text @@ -252,6 +281,8 @@ Implemented: * Shared secrets stored outside Git repositories * SSL certificates managed through Nginx Proxy Manager * PostgreSQL not exposed publicly +* MSSQL port 1433 not exposed publicly +* Database administration is available only through authenticated HTTPS access to DbGate * OpenID disabled in Gitea --- diff --git a/docs/services.md b/docs/services.md index 1752c50..4b3bec3 100644 --- a/docs/services.md +++ b/docs/services.md @@ -135,6 +135,38 @@ Running --- +### Microsoft SQL Server Express + +Purpose: + +* Support applications requiring Microsoft SQL Server +* Run alongside PostgreSQL as a private database platform + +Image: + +```text +mcr.microsoft.com/mssql/server:2022-latest +``` + +Network: + +```text +internal +``` + +Exposure: + +* Port 1433 is not published +* Not routed through Nginx Proxy Manager + +Status: + +```text +Operational +``` + +--- + ### BaGet URL: @@ -202,6 +234,38 @@ Operational --- +### DbGate + +URL: + +```text +https://dbgate.silveressence.net +``` + +Purpose: + +* Browser-based MSSQL administration +* Browser-based PostgreSQL administration + +Networks: + +* `internal` for private database connectivity +* `proxy` for Nginx Proxy Manager + +Security: + +* HTTPS enforced +* DbGate username and password required +* Database ports remain private + +Status: + +```text +Operational +``` + +--- + ## Shared Infrastructure ### Docker diff --git a/mssql/README.md b/mssql/README.md new file mode 100644 index 0000000..3ce1f78 --- /dev/null +++ b/mssql/README.md @@ -0,0 +1,117 @@ +# Microsoft SQL Server Express + +## Overview + +Microsoft SQL Server 2022 Express runs alongside PostgreSQL for Silver projects that require Microsoft SQL Server compatibility. + +Status: + +```text +Operational +``` + +Verified version: + +```text +Microsoft SQL Server 2022 Express Edition (64-bit) +Linux +Version 16.0.4255.1 +``` + +--- + +## Service Information + +| Property | Value | +| --- | --- | +| Container | `mssql` | +| Image | `mcr.microsoft.com/mssql/server:2022-latest` | +| Edition | Express | +| Docker network | `internal` | +| Compose location | `/srv/docker/mssql/docker-compose.yml` | +| Data location | `/srv/docker/mssql/data` | + +Port `1433` is not published by Docker or exposed through Nginx Proxy Manager. Applications connect privately over the `internal` Docker network using hostname `mssql`. + +Server-side administration must use `docker exec` or another container attached to `internal`; there is no host-bound SQL port in the current configuration. + +--- + +## Secrets + +The SA password is stored outside the repository: + +```text +/srv/secrets/company.env +MSSQL_SA_PASSWORD +``` + +Never commit the value to Git or place it directly in the Compose file. + +--- + +## Deployment + +Docker Compose must be given the secrets file for interpolation: + +```bash +cd /srv/docker/mssql +docker compose --env-file /srv/secrets/company.env up -d +``` + +The Compose `env_file:` setting passes variables into the container. It does not make them available while Compose resolves `${MSSQL_SA_PASSWORD}`, which is why `--env-file` is required. + +Validate startup: + +```bash +docker ps +docker logs mssql +``` + +Expected log message: + +```text +SQL Server is now ready for client connections. +``` + +--- + +## Data Directory Permissions + +The SQL Server container runs as UID and GID `10001`. For a new, empty deployment, initialize the bind-mounted directory with: + +```bash +sudo mkdir -p /srv/docker/mssql/data +sudo chown -R 10001:10001 /srv/docker/mssql/data +sudo chmod -R 700 /srv/docker/mssql/data +``` + +Do not delete or recreate the directory after databases exist. Removing `/srv/docker/mssql/data` destroys the persisted SQL Server data. + +--- + +## Troubleshooting + +### Variable Is Not Set + +If Compose reports that `MSSQL_SA_PASSWORD` is unset and defaults to a blank string, use the required `docker compose --env-file /srv/secrets/company.env up -d` command. + +### System Directory Permission Denied + +If `[/.system]` cannot be created, verify that `/srv/docker/mssql/data` is owned by `10001:10001` with mode `700`. + +### Password Validation Failed + +Confirm that the password meets SQL Server complexity requirements and that Compose resolved `MSSQL_SA_PASSWORD` from the secrets file. + +--- + +## Related Documentation + +* docs/server.md +* docs/services.md +* docs/security.md +* docs/secrets.md +* docs/backups.md +* dbgate/README.md +* postgres/README.md diff --git a/mssql/docker-compose.yml b/mssql/docker-compose.yml new file mode 100644 index 0000000..8911f7e --- /dev/null +++ b/mssql/docker-compose.yml @@ -0,0 +1,19 @@ +services: + mssql: + image: mcr.microsoft.com/mssql/server:2022-latest + container_name: mssql + restart: unless-stopped + env_file: + - /srv/secrets/company.env + environment: + ACCEPT_EULA: Y + MSSQL_PID: Express + MSSQL_SA_PASSWORD: ${MSSQL_SA_PASSWORD} + volumes: + - /srv/docker/mssql/data:/var/opt/mssql + networks: + - internal + +networks: + internal: + external: true diff --git a/nginx-proxy-manager/README.md b/nginx-proxy-manager/README.md index 7ea8d9f..65f013f 100644 --- a/nginx-proxy-manager/README.md +++ b/nginx-proxy-manager/README.md @@ -99,6 +99,7 @@ Examples: | meet.silveressence.net | Jitsi | | portainer.silveressence.net | Portainer | | nuget.silveressence.net | BaGet | +| dbgate.silveressence.net | DbGate | --- @@ -195,6 +196,7 @@ Without these directories: * Jitsi Meet * Portainer * BaGet +* DbGate --- diff --git a/postgres/README.md b/postgres/README.md index c8a3ad9..614a1ba 100644 --- a/postgres/README.md +++ b/postgres/README.md @@ -2,7 +2,7 @@ ## Overview -PostgreSQL is the central database platform for SilverLinux. +PostgreSQL is the primary open-source database platform for SilverLinux and coexists with Microsoft SQL Server 2022 Express. Multiple applications use the same PostgreSQL instance while maintaining separate databases and database users. @@ -278,6 +278,8 @@ Without the secrets file, applications may not be able to reconnect to their dat * Gitea * OpenProject +* DbGate +* Microsoft SQL Server Express ## Related Documentation