version .1
Some checks failed
Build and Publish Docker Image / build-and-push (push) Has been cancelled
Some checks failed
Build and Publish Docker Image / build-and-push (push) Has been cancelled
This commit is contained in:
Submodule .template-cache/2dc03e2b2b45fef3 updated: 292fbb4bfe...af33306def
@@ -33,7 +33,6 @@ public static class AppConstants
|
|||||||
public static string[] AllCustomerMysqlSecretNames(string abbrev)
|
public static string[] AllCustomerMysqlSecretNames(string abbrev)
|
||||||
=> new[]
|
=> new[]
|
||||||
{
|
{
|
||||||
CustomerMysqlPasswordSecretName(abbrev),
|
|
||||||
CustomerMysqlUserSecretName(abbrev),
|
CustomerMysqlUserSecretName(abbrev),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ public class ComposeRenderService
|
|||||||
.Replace("{{MYSQL_PORT}}", ctx.MySqlPort)
|
.Replace("{{MYSQL_PORT}}", ctx.MySqlPort)
|
||||||
.Replace("{{MYSQL_DATABASE}}", ctx.MySqlDatabase)
|
.Replace("{{MYSQL_DATABASE}}", ctx.MySqlDatabase)
|
||||||
.Replace("{{MYSQL_USER}}", ctx.MySqlUser)
|
.Replace("{{MYSQL_USER}}", ctx.MySqlUser)
|
||||||
|
.Replace("{{MYSQL_PASSWORD}}", ctx.MySqlPassword)
|
||||||
.Replace("{{SMTP_SERVER}}", ctx.SmtpServer)
|
.Replace("{{SMTP_SERVER}}", ctx.SmtpServer)
|
||||||
.Replace("{{SMTP_USERNAME}}", ctx.SmtpUsername)
|
.Replace("{{SMTP_USERNAME}}", ctx.SmtpUsername)
|
||||||
.Replace("{{SMTP_PASSWORD}}", ctx.SmtpPassword)
|
.Replace("{{SMTP_PASSWORD}}", ctx.SmtpPassword)
|
||||||
@@ -168,7 +169,7 @@ public class ComposeRenderService
|
|||||||
MYSQL_PORT: "{{MYSQL_PORT}}"
|
MYSQL_PORT: "{{MYSQL_PORT}}"
|
||||||
MYSQL_DATABASE: {{MYSQL_DATABASE}}
|
MYSQL_DATABASE: {{MYSQL_DATABASE}}
|
||||||
MYSQL_USER: {{MYSQL_USER}}
|
MYSQL_USER: {{MYSQL_USER}}
|
||||||
MYSQL_PASSWORD_FILE: /run/secrets/{{ABBREV}}-cms-db-password
|
MYSQL_PASSWORD: {{MYSQL_PASSWORD}}
|
||||||
CMS_SERVER_NAME: {{CMS_SERVER_NAME}}
|
CMS_SERVER_NAME: {{CMS_SERVER_NAME}}
|
||||||
CMS_SMTP_SERVER: {{SMTP_SERVER}}
|
CMS_SMTP_SERVER: {{SMTP_SERVER}}
|
||||||
CMS_SMTP_USERNAME: {{SMTP_USERNAME}}
|
CMS_SMTP_USERNAME: {{SMTP_USERNAME}}
|
||||||
@@ -182,7 +183,6 @@ public class ComposeRenderService
|
|||||||
CMS_PHP_UPLOAD_MAX_FILESIZE: {{PHP_UPLOAD_MAX_FILESIZE}}
|
CMS_PHP_UPLOAD_MAX_FILESIZE: {{PHP_UPLOAD_MAX_FILESIZE}}
|
||||||
CMS_PHP_MAX_EXECUTION_TIME: "{{PHP_MAX_EXECUTION_TIME}}"
|
CMS_PHP_MAX_EXECUTION_TIME: "{{PHP_MAX_EXECUTION_TIME}}"
|
||||||
secrets:
|
secrets:
|
||||||
- {{ABBREV}}-cms-db-password
|
|
||||||
- {{ABBREV}}-cms-db-user
|
- {{ABBREV}}-cms-db-user
|
||||||
- global_mysql_host
|
- global_mysql_host
|
||||||
- global_mysql_port
|
- global_mysql_port
|
||||||
@@ -280,8 +280,6 @@ public class ComposeRenderService
|
|||||||
o: "{{NFS_OPTS}}"
|
o: "{{NFS_OPTS}}"
|
||||||
|
|
||||||
secrets:
|
secrets:
|
||||||
{{ABBREV}}-cms-db-password:
|
|
||||||
external: true
|
|
||||||
{{ABBREV}}-cms-db-user:
|
{{ABBREV}}-cms-db-user:
|
||||||
external: true
|
external: true
|
||||||
global_mysql_host:
|
global_mysql_host:
|
||||||
@@ -314,6 +312,7 @@ public class RenderContext
|
|||||||
public string MySqlPort { get; set; } = "3306";
|
public string MySqlPort { get; set; } = "3306";
|
||||||
public string MySqlDatabase { get; set; } = "cms";
|
public string MySqlDatabase { get; set; } = "cms";
|
||||||
public string MySqlUser { get; set; } = "cms";
|
public string MySqlUser { get; set; } = "cms";
|
||||||
|
public string MySqlPassword { get; set; } = string.Empty;
|
||||||
|
|
||||||
// SMTP
|
// SMTP
|
||||||
public string SmtpServer { get; set; } = string.Empty;
|
public string SmtpServer { get; set; } = string.Empty;
|
||||||
|
|||||||
@@ -111,7 +111,6 @@ public class ComposeValidationService
|
|||||||
{
|
{
|
||||||
var requiredSecrets = new[]
|
var requiredSecrets = new[]
|
||||||
{
|
{
|
||||||
AppConstants.CustomerMysqlPasswordSecretName(customerAbbrev),
|
|
||||||
AppConstants.CustomerMysqlUserSecretName(customerAbbrev),
|
AppConstants.CustomerMysqlUserSecretName(customerAbbrev),
|
||||||
AppConstants.GlobalMysqlHostSecretName,
|
AppConstants.GlobalMysqlHostSecretName,
|
||||||
AppConstants.GlobalMysqlPortSecretName,
|
AppConstants.GlobalMysqlPortSecretName,
|
||||||
|
|||||||
@@ -101,18 +101,12 @@ public class InstanceService
|
|||||||
await _docker.RemoveStackAsync(stackName);
|
await _docker.RemoveStackAsync(stackName);
|
||||||
await Task.Delay(2000);
|
await Task.Delay(2000);
|
||||||
|
|
||||||
// ── 2. Generate MySQL credentials → Docker Swarm secrets ────────
|
// ── 2. Generate MySQL credentials ──────────────────────────────
|
||||||
var mysqlPassword = GenerateRandomPassword(32);
|
var mysqlPassword = GenerateRandomPassword(32);
|
||||||
var mySqlUserName = (await _settings.GetAsync(SettingsService.DefaultMySqlUserTemplate, "{abbrev}_cms_user")).Replace("{abbrev}", abbrev);
|
var mySqlUserName = (await _settings.GetAsync(SettingsService.DefaultMySqlUserTemplate, "{abbrev}_cms_user")).Replace("{abbrev}", abbrev);
|
||||||
|
|
||||||
var pwdSecretName = CustomerMysqlPasswordSecretName(abbrev);
|
|
||||||
var userSecretName = CustomerMysqlUserSecretName(abbrev);
|
var userSecretName = CustomerMysqlUserSecretName(abbrev);
|
||||||
|
|
||||||
var (pwdOk, _) = await _secrets.EnsureSecretAsync(pwdSecretName, mysqlPassword, rotate: true);
|
|
||||||
if (!pwdOk)
|
|
||||||
throw new InvalidOperationException($"Failed to create/rotate Docker secret '{pwdSecretName}'. Is a stale stack still referencing it?");
|
|
||||||
_logger.LogInformation("Docker secret created/rotated: {SecretName}", pwdSecretName);
|
|
||||||
|
|
||||||
var (userOk, _) = await _secrets.EnsureSecretAsync(userSecretName, mySqlUserName, rotate: true);
|
var (userOk, _) = await _secrets.EnsureSecretAsync(userSecretName, mySqlUserName, rotate: true);
|
||||||
if (!userOk)
|
if (!userOk)
|
||||||
throw new InvalidOperationException($"Failed to create/rotate Docker secret '{userSecretName}'.");
|
throw new InvalidOperationException($"Failed to create/rotate Docker secret '{userSecretName}'.");
|
||||||
@@ -132,7 +126,12 @@ public class InstanceService
|
|||||||
throw new InvalidOperationException($"MySQL database/user setup failed: {mysqlMsg}");
|
throw new InvalidOperationException($"MySQL database/user setup failed: {mysqlMsg}");
|
||||||
_logger.LogInformation("MySQL setup complete: {Message}", mysqlMsg);
|
_logger.LogInformation("MySQL setup complete: {Message}", mysqlMsg);
|
||||||
|
|
||||||
mysqlPassword = string.Empty;
|
// ── 2c. Persist password (encrypted) for future redeploys ────────
|
||||||
|
await _settings.SetAsync(
|
||||||
|
SettingsService.InstanceMySqlPassword(abbrev), mysqlPassword,
|
||||||
|
SettingsService.CatInstance, isSensitive: true);
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
|
_logger.LogInformation("MySQL password stored in settings for instance {Abbrev}", abbrev);
|
||||||
|
|
||||||
// ── 3. Read settings ────────────────────────────────────────────
|
// ── 3. Read settings ────────────────────────────────────────────
|
||||||
var mySqlHost = mySqlHostValue;
|
var mySqlHost = mySqlHostValue;
|
||||||
@@ -185,6 +184,7 @@ public class InstanceService
|
|||||||
MySqlPort = mySqlPort,
|
MySqlPort = mySqlPort,
|
||||||
MySqlDatabase = mySqlDbName,
|
MySqlDatabase = mySqlDbName,
|
||||||
MySqlUser = mySqlUser,
|
MySqlUser = mySqlUser,
|
||||||
|
MySqlPassword = mysqlPassword,
|
||||||
SmtpServer = smtpServer,
|
SmtpServer = smtpServer,
|
||||||
SmtpUsername = smtpUsername,
|
SmtpUsername = smtpUsername,
|
||||||
SmtpPassword = smtpPassword,
|
SmtpPassword = smtpPassword,
|
||||||
@@ -244,6 +244,8 @@ public class InstanceService
|
|||||||
if (!deployResult.Success)
|
if (!deployResult.Success)
|
||||||
throw new InvalidOperationException($"Stack deployment failed: {deployResult.ErrorMessage}");
|
throw new InvalidOperationException($"Stack deployment failed: {deployResult.ErrorMessage}");
|
||||||
|
|
||||||
|
mysqlPassword = string.Empty;
|
||||||
|
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
opLog.Status = OperationStatus.Success;
|
opLog.Status = OperationStatus.Success;
|
||||||
opLog.Message = $"Instance deployed: {stackName}";
|
opLog.Message = $"Instance deployed: {stackName}";
|
||||||
@@ -296,6 +298,14 @@ public class InstanceService
|
|||||||
var mySqlDbName = (await _settings.GetAsync(SettingsService.DefaultMySqlDbTemplate, "{abbrev}_cms_db")).Replace("{abbrev}", abbrev);
|
var mySqlDbName = (await _settings.GetAsync(SettingsService.DefaultMySqlDbTemplate, "{abbrev}_cms_db")).Replace("{abbrev}", abbrev);
|
||||||
var mySqlUser = (await _settings.GetAsync(SettingsService.DefaultMySqlUserTemplate, "{abbrev}_cms_user")).Replace("{abbrev}", abbrev);
|
var mySqlUser = (await _settings.GetAsync(SettingsService.DefaultMySqlUserTemplate, "{abbrev}_cms_user")).Replace("{abbrev}", abbrev);
|
||||||
|
|
||||||
|
// Retrieve the stored MySQL password (encrypted in settings since creation)
|
||||||
|
var mySqlPassword = await _settings.GetAsync(SettingsService.InstanceMySqlPassword(abbrev));
|
||||||
|
if (string.IsNullOrEmpty(mySqlPassword))
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"No stored MySQL password found for instance '{abbrev}'. " +
|
||||||
|
"The instance may have been created before password persistence was added. " +
|
||||||
|
"Use 'Rotate Password' to generate and store a new one.");
|
||||||
|
|
||||||
// Ensure MySQL Docker secrets exist (idempotent)
|
// Ensure MySQL Docker secrets exist (idempotent)
|
||||||
var userSecretName = CustomerMysqlUserSecretName(abbrev);
|
var userSecretName = CustomerMysqlUserSecretName(abbrev);
|
||||||
await _secrets.EnsureSecretAsync(userSecretName, mySqlUser);
|
await _secrets.EnsureSecretAsync(userSecretName, mySqlUser);
|
||||||
@@ -357,6 +367,7 @@ public class InstanceService
|
|||||||
MySqlPort = mySqlPort,
|
MySqlPort = mySqlPort,
|
||||||
MySqlDatabase = mySqlDbName,
|
MySqlDatabase = mySqlDbName,
|
||||||
MySqlUser = mySqlUser,
|
MySqlUser = mySqlUser,
|
||||||
|
MySqlPassword = mySqlPassword,
|
||||||
SmtpServer = smtpServer,
|
SmtpServer = smtpServer,
|
||||||
SmtpUsername = smtpUsername,
|
SmtpUsername = smtpUsername,
|
||||||
SmtpPassword = smtpPassword,
|
SmtpPassword = smtpPassword,
|
||||||
@@ -470,6 +481,12 @@ public class InstanceService
|
|||||||
|
|
||||||
foreach (var secretName in AllCustomerMysqlSecretNames(abbrev))
|
foreach (var secretName in AllCustomerMysqlSecretNames(abbrev))
|
||||||
await _secrets.DeleteSecretAsync(secretName);
|
await _secrets.DeleteSecretAsync(secretName);
|
||||||
|
|
||||||
|
// Remove the stored password from local settings
|
||||||
|
await _settings.SetAsync(
|
||||||
|
SettingsService.InstanceMySqlPassword(abbrev), null,
|
||||||
|
SettingsService.CatInstance, isSensitive: false);
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
@@ -506,23 +523,11 @@ public class InstanceService
|
|||||||
public async Task<(bool Success, string Message)> RotateMySqlPasswordAsync(string stackName, string? userId = null)
|
public async Task<(bool Success, string Message)> RotateMySqlPasswordAsync(string stackName, string? userId = null)
|
||||||
{
|
{
|
||||||
var abbrev = ExtractAbbrev(stackName);
|
var abbrev = ExtractAbbrev(stackName);
|
||||||
var secretName = CustomerMysqlPasswordSecretName(abbrev);
|
|
||||||
var tempSecret = $"{secretName}-rot";
|
|
||||||
var webService = $"{stackName}_{abbrev}-web";
|
|
||||||
var newPassword = GenerateRandomPassword(32);
|
var newPassword = GenerateRandomPassword(32);
|
||||||
|
|
||||||
_logger.LogInformation("Rotating MySQL password for instance {StackName}", stackName);
|
_logger.LogInformation("Rotating MySQL password for instance {StackName}", stackName);
|
||||||
|
|
||||||
// ── Step 1: Create temp secret (new value, different name) ────────────
|
// ── Step 1: Update MySQL password via SSH tunnel ─────────────────────
|
||||||
// We cannot delete the live secret while the service is using it, so we
|
|
||||||
// stage the new value under a temporary name first.
|
|
||||||
var (tempCreated, _) = await _secrets.EnsureSecretAsync(tempSecret, newPassword, rotate: false);
|
|
||||||
if (!tempCreated)
|
|
||||||
return (false, $"Failed to create temporary rotation secret '{tempSecret}'.");
|
|
||||||
|
|
||||||
// ── Step 2: Update MySQL password via SSH ─────────────────────────────
|
|
||||||
// Connect through the Docker SSH host so the desktop app doesn't need
|
|
||||||
// direct TCP access to the MySQL server.
|
|
||||||
var mySqlHost = await _settings.GetAsync(SettingsService.MySqlHost, "localhost");
|
var mySqlHost = await _settings.GetAsync(SettingsService.MySqlHost, "localhost");
|
||||||
var mySqlPort = await _settings.GetAsync(SettingsService.MySqlPort, "3306");
|
var mySqlPort = await _settings.GetAsync(SettingsService.MySqlPort, "3306");
|
||||||
var mySqlAdminUser = await _settings.GetAsync(SettingsService.MySqlAdminUser, "root");
|
var mySqlAdminUser = await _settings.GetAsync(SettingsService.MySqlAdminUser, "root");
|
||||||
@@ -535,51 +540,30 @@ public class InstanceService
|
|||||||
mySqlHost, port, mySqlAdminUser, mySqlAdminPassword, mySqlUser, newPassword);
|
mySqlHost, port, mySqlAdminUser, mySqlAdminPassword, mySqlUser, newPassword);
|
||||||
|
|
||||||
if (!mysqlOk)
|
if (!mysqlOk)
|
||||||
{
|
return (false, $"MySQL ALTER USER failed (no service disruption): {mysqlErr}");
|
||||||
// No service swap has happened yet — clean up temp and abort cleanly.
|
|
||||||
await _secrets.DeleteSecretAsync(tempSecret);
|
|
||||||
return (false, $"MySQL update failed (no service disruption): {mysqlErr}");
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.LogInformation("MySQL password updated for user {User}", mySqlUser);
|
_logger.LogInformation("MySQL password updated for user {User}", mySqlUser);
|
||||||
|
|
||||||
// ── Step 3: Swap service from old secret → temp (same /run/secrets/ path)
|
// ── Step 2: Persist new password in settings (encrypted) ─────────────
|
||||||
// Triggers rolling restart; containers pick up the new password.
|
await _settings.SetAsync(
|
||||||
if (!await _docker.ServiceSwapSecretAsync(webService, secretName, tempSecret, targetAlias: secretName))
|
SettingsService.InstanceMySqlPassword(abbrev), newPassword,
|
||||||
{
|
SettingsService.CatInstance, isSensitive: true);
|
||||||
// Rollback MySQL — try to restore old password. We don't know it, so
|
await _db.SaveChangesAsync();
|
||||||
// log a warning; the temp secret can be cleaned up manually.
|
_logger.LogInformation("New MySQL password stored in settings for instance {Abbrev}", abbrev);
|
||||||
_logger.LogError(
|
|
||||||
"Service swap failed. MySQL has new password but service still uses old secret. " +
|
|
||||||
"Manual intervention may be required for {Service}", webService);
|
|
||||||
return (false, $"Service swap failed for '{webService}'. MySQL password was updated but secret swap did not complete.");
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.LogInformation("Service {Service} rolling restart with temp secret {TempSecret}", webService, tempSecret);
|
// ── Step 3: Force-update the web service to pick up new compose env ──
|
||||||
|
// Redeploy the stack so the MYSQL_PASSWORD env var gets the new value.
|
||||||
// ── Step 4: Delete the old secret (now unreferenced by any service) ───
|
var webService = $"{stackName}_{abbrev}-web";
|
||||||
await _secrets.DeleteSecretAsync(secretName);
|
if (!await _docker.ForceUpdateServiceAsync(webService))
|
||||||
|
|
||||||
// ── Step 5: Recreate permanent secret under the original name ─────────
|
|
||||||
var (secretCreated, secretId) = await _secrets.EnsureSecretAsync(secretName, newPassword, rotate: false);
|
|
||||||
if (!secretCreated)
|
|
||||||
{
|
|
||||||
_logger.LogError("Failed to recreate permanent secret {SecretName}; temp secret remains active", secretName);
|
|
||||||
return (false, $"Rotation partially complete: temp secret '{tempSecret}' is active but '{secretName}' could not be recreated.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Step 6: Swap service back to permanent name; second rolling restart ─
|
|
||||||
if (!await _docker.ServiceSwapSecretAsync(webService, tempSecret, secretName))
|
|
||||||
{
|
{
|
||||||
_logger.LogWarning(
|
_logger.LogWarning(
|
||||||
"Final swap to permanent secret failed for {Service}; temp secret '{TempSecret}' is still active. " +
|
"Force-update of service {Service} failed. MySQL has the new password but " +
|
||||||
"Service is functional but secret name normalisation is pending.", webService, tempSecret);
|
"the container is still running with the old value. A manual redeploy may be needed.",
|
||||||
return (true, $"MySQL password rotated for '{stackName}' (temp secret active; manual final swap may be needed).");
|
webService);
|
||||||
|
return (true, $"MySQL password rotated for '{stackName}' but service force-update failed. Redeploy to apply.");
|
||||||
}
|
}
|
||||||
|
|
||||||
await _secrets.DeleteSecretAsync(tempSecret);
|
_logger.LogInformation("Service {Service} force-updated with new password", webService);
|
||||||
|
|
||||||
_logger.LogInformation("Docker secret fully rotated: {SecretName} (new id={SecretId})", secretName, secretId);
|
|
||||||
return (true, $"MySQL password rotated successfully for '{stackName}'.");
|
return (true, $"MySQL password rotated successfully for '{stackName}'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -750,8 +734,6 @@ public class InstanceService
|
|||||||
|
|
||||||
private static string GenerateRandomPassword(int length)
|
private static string GenerateRandomPassword(int length)
|
||||||
{
|
{
|
||||||
// Only alphanumeric chars — special characters (! @ # $ % ^ & *) can be
|
|
||||||
// mangled by shell escaping in the printf→docker-secret-create SSH pipeline.
|
|
||||||
const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||||
return RandomNumberGenerator.GetString(chars, length);
|
return RandomNumberGenerator.GetString(chars, length);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,14 @@ public class SettingsService
|
|||||||
public const string DefaultPhpUploadMaxFilesize = "Defaults.PhpUploadMaxFilesize";
|
public const string DefaultPhpUploadMaxFilesize = "Defaults.PhpUploadMaxFilesize";
|
||||||
public const string DefaultPhpMaxExecutionTime = "Defaults.PhpMaxExecutionTime";
|
public const string DefaultPhpMaxExecutionTime = "Defaults.PhpMaxExecutionTime";
|
||||||
|
|
||||||
|
// Instance-specific (keyed by abbreviation)
|
||||||
|
/// <summary>
|
||||||
|
/// Builds a per-instance settings key for the MySQL password.
|
||||||
|
/// Stored encrypted via DataProtection so it can be retrieved on update/redeploy.
|
||||||
|
/// </summary>
|
||||||
|
public static string InstanceMySqlPassword(string abbrev) => $"Instance.{abbrev}.MySqlPassword";
|
||||||
|
public const string CatInstance = "Instance";
|
||||||
|
|
||||||
public SettingsService(
|
public SettingsService(
|
||||||
XiboContext db,
|
XiboContext db,
|
||||||
IDataProtectionProvider dataProtection,
|
IDataProtectionProvider dataProtection,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Text;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using OTSSignsOrchestrator.Core.Models.Entities;
|
using OTSSignsOrchestrator.Core.Models.Entities;
|
||||||
using OTSSignsOrchestrator.Core.Services;
|
using OTSSignsOrchestrator.Core.Services;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ services:
|
|||||||
MYSQL_PORT: "{{MYSQL_PORT}}"
|
MYSQL_PORT: "{{MYSQL_PORT}}"
|
||||||
MYSQL_DATABASE: {{MYSQL_DATABASE}}
|
MYSQL_DATABASE: {{MYSQL_DATABASE}}
|
||||||
MYSQL_USER: {{MYSQL_USER}}
|
MYSQL_USER: {{MYSQL_USER}}
|
||||||
MYSQL_PASSWORD_FILE: /run/secrets/{{ABBREV}}-cms-db-password
|
MYSQL_PASSWORD: {{MYSQL_PASSWORD}}
|
||||||
CMS_SERVER_NAME: {{CMS_SERVER_NAME}}
|
CMS_SERVER_NAME: {{CMS_SERVER_NAME}}
|
||||||
CMS_SMTP_SERVER: {{SMTP_SERVER}}
|
CMS_SMTP_SERVER: {{SMTP_SERVER}}
|
||||||
CMS_SMTP_USERNAME: {{SMTP_USERNAME}}
|
CMS_SMTP_USERNAME: {{SMTP_USERNAME}}
|
||||||
@@ -26,7 +26,6 @@ services:
|
|||||||
CMS_PHP_UPLOAD_MAX_FILESIZE: {{PHP_UPLOAD_MAX_FILESIZE}}
|
CMS_PHP_UPLOAD_MAX_FILESIZE: {{PHP_UPLOAD_MAX_FILESIZE}}
|
||||||
CMS_PHP_MAX_EXECUTION_TIME: "{{PHP_MAX_EXECUTION_TIME}}"
|
CMS_PHP_MAX_EXECUTION_TIME: "{{PHP_MAX_EXECUTION_TIME}}"
|
||||||
secrets:
|
secrets:
|
||||||
- {{ABBREV}}-cms-db-password
|
|
||||||
- {{ABBREV}}-cms-db-user
|
- {{ABBREV}}-cms-db-user
|
||||||
- global_mysql_host
|
- global_mysql_host
|
||||||
- global_mysql_port
|
- global_mysql_port
|
||||||
@@ -124,8 +123,6 @@ volumes:
|
|||||||
o: "{{NFS_OPTS}}"
|
o: "{{NFS_OPTS}}"
|
||||||
|
|
||||||
secrets:
|
secrets:
|
||||||
{{ABBREV}}-cms-db-password:
|
|
||||||
external: true
|
|
||||||
{{ABBREV}}-cms-db-user:
|
{{ABBREV}}-cms-db-user:
|
||||||
external: true
|
external: true
|
||||||
global_mysql_host:
|
global_mysql_host:
|
||||||
|
|||||||
Reference in New Issue
Block a user