Added support for environment variables
This adds support for supplying the commandline settings via environment variables. Rolled back the previous fix to support only a few variables. Cleaned some types to use more consistent types. This fixes #5453
This commit is contained in:
+46
-41
@@ -36,9 +36,9 @@ namespace Duplicati.Server
|
||||
public class Program
|
||||
{
|
||||
|
||||
private static readonly List<string> AlternativeHelpStrings = new List<string> { "help", "/help", "usage", "/usage", "--help" };
|
||||
private static readonly string[] AlternativeHelpStrings = ["help", "/help", "usage", "/usage", "--help"];
|
||||
|
||||
private static readonly List<string> ParameterFileOptionStrings = new List<string> { "parameters-file", "parameterfile" };
|
||||
private static readonly string[] ParameterFileOptionStrings = ["parameters-file", "parameterfile"];
|
||||
|
||||
#if DEBUG
|
||||
private const bool DEBUG_MODE = true;
|
||||
@@ -60,10 +60,15 @@ namespace Duplicati.Server
|
||||
/// </summary>
|
||||
private const string SERVER_DATABASE_FILENAME = "Duplicati-server.sqlite";
|
||||
|
||||
/// <summary>
|
||||
/// The environment variable prefix
|
||||
/// </summary>
|
||||
private static readonly string ENV_NAME_PREFIX = Duplicati.Library.AutoUpdater.AutoUpdateSettings.AppName.ToUpper(CultureInfo.InvariantCulture);
|
||||
|
||||
/// <summary>
|
||||
/// The name of the environment variable that holds the path to the data folder used by Duplicati
|
||||
/// </summary>
|
||||
private static readonly string DATAFOLDER_ENV_NAME = Duplicati.Library.AutoUpdater.AutoUpdateSettings.AppName.ToUpper(CultureInfo.InvariantCulture) + "_HOME";
|
||||
private static readonly string DATAFOLDER_ENV_NAME = ENV_NAME_PREFIX + "_HOME";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the folder where Duplicati data is stored
|
||||
@@ -212,7 +217,7 @@ namespace Duplicati.Server
|
||||
var commandlineOptions = optionsWithFilter.Item1;
|
||||
var filter = optionsWithFilter.Item2;
|
||||
|
||||
if (_args.Select(s => s.ToLower()).Intersect(AlternativeHelpStrings.ConvertAll(x => x.ToLower())).Any())
|
||||
if (_args.Select(s => s.ToLower()).Intersect(AlternativeHelpStrings.Select(x => x.ToLower())).Any())
|
||||
{
|
||||
return ShowHelp(writeToConsole);
|
||||
}
|
||||
@@ -224,8 +229,10 @@ namespace Duplicati.Server
|
||||
|
||||
Library.Utility.SystemContextSettings.StartSession();
|
||||
|
||||
ApplyEnvironmentVariables(commandlineOptions);
|
||||
|
||||
var parameterFileOption = commandlineOptions.Keys.Select(s => s.ToLower())
|
||||
.Intersect(ParameterFileOptionStrings.ConvertAll(x => x.ToLower())).FirstOrDefault();
|
||||
.Intersect(ParameterFileOptionStrings.Select(x => x.ToLower())).FirstOrDefault();
|
||||
|
||||
if (parameterFileOption != null && !string.IsNullOrEmpty(commandlineOptions[parameterFileOption]))
|
||||
{
|
||||
@@ -478,9 +485,6 @@ namespace Duplicati.Server
|
||||
#endif
|
||||
}
|
||||
|
||||
private static string? GetEnvironmentVariableForOption(string name)
|
||||
=> Environment.GetEnvironmentVariable((name ?? "").Replace('-', '_').ToUpperInvariant().Trim());
|
||||
|
||||
private static void AdjustApplicationSettings(Dictionary<string, string> commandlineOptions)
|
||||
{
|
||||
// This clears the JWT config, and a new will be generated, invalidating all existing tokens
|
||||
@@ -493,17 +497,11 @@ namespace Duplicati.Server
|
||||
|
||||
if (commandlineOptions.ContainsKey(WebServerLoader.OPTION_WEBSERVICE_PASSWORD))
|
||||
DataConnection.ApplicationSettings.SetWebserverPassword(commandlineOptions[WebServerLoader.OPTION_WEBSERVICE_PASSWORD]);
|
||||
else if (!string.IsNullOrWhiteSpace(GetEnvironmentVariableForOption(WebServerLoader.OPTION_WEBSERVICE_PASSWORD)))
|
||||
DataConnection.ApplicationSettings.SetWebserverPassword(GetEnvironmentVariableForOption(WebServerLoader.OPTION_WEBSERVICE_PASSWORD));
|
||||
|
||||
if (commandlineOptions.ContainsKey(WebServerLoader.OPTION_WEBSERVICE_ALLOWEDHOSTNAMES))
|
||||
DataConnection.ApplicationSettings.SetAllowedHostnames(commandlineOptions[WebServerLoader.OPTION_WEBSERVICE_ALLOWEDHOSTNAMES]);
|
||||
else if (commandlineOptions.ContainsKey(WebServerLoader.OPTION_WEBSERVICE_ALLOWEDHOSTNAMES_ALT))
|
||||
DataConnection.ApplicationSettings.SetAllowedHostnames(commandlineOptions[WebServerLoader.OPTION_WEBSERVICE_ALLOWEDHOSTNAMES_ALT]);
|
||||
else if (!string.IsNullOrWhiteSpace(GetEnvironmentVariableForOption(WebServerLoader.OPTION_WEBSERVICE_ALLOWEDHOSTNAMES)))
|
||||
DataConnection.ApplicationSettings.SetAllowedHostnames(GetEnvironmentVariableForOption(WebServerLoader.OPTION_WEBSERVICE_ALLOWEDHOSTNAMES));
|
||||
else if (!string.IsNullOrWhiteSpace(GetEnvironmentVariableForOption(WebServerLoader.OPTION_WEBSERVICE_ALLOWEDHOSTNAMES_ALT)))
|
||||
DataConnection.ApplicationSettings.SetAllowedHostnames(GetEnvironmentVariableForOption(WebServerLoader.OPTION_WEBSERVICE_ALLOWEDHOSTNAMES_ALT));
|
||||
}
|
||||
|
||||
private static void CreateApplicationInstance(bool writeConsole)
|
||||
@@ -536,6 +534,21 @@ namespace Duplicati.Server
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplyEnvironmentVariables(Dictionary<string, string> commandlineOptions)
|
||||
{
|
||||
foreach (var key in SupportedCommands.SelectMany(x => (x.Aliases ?? []).Prepend(x.Name)).Distinct())
|
||||
{
|
||||
// Commandline options take precedence
|
||||
if (commandlineOptions.ContainsKey(key))
|
||||
continue;
|
||||
|
||||
var envkey = $"{ENV_NAME_PREFIX}__{key.Replace('-', '_').ToUpperInvariant()}";
|
||||
var envval = Environment.GetEnvironmentVariable(envkey);
|
||||
if (!string.IsNullOrWhiteSpace(envval))
|
||||
commandlineOptions[key] = envval;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ConfigureLogging(Dictionary<string, string> commandlineOptions)
|
||||
{
|
||||
|
||||
@@ -794,33 +807,25 @@ namespace Duplicati.Server
|
||||
/// Gets a list of all supported commandline options
|
||||
/// </summary>
|
||||
public static Library.Interface.ICommandLineArgument[] SupportedCommands
|
||||
{
|
||||
get
|
||||
{
|
||||
var lst = new List<Duplicati.Library.Interface.ICommandLineArgument>(new Duplicati.Library.Interface.ICommandLineArgument[] {
|
||||
new Duplicati.Library.Interface.CommandLineArgument("tempdir", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Path, Strings.Program.TempdirShort, Strings.Program.TempdirLong, System.IO.Path.GetTempPath()),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("help", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Boolean, Strings.Program.HelpCommandDescription, Strings.Program.HelpCommandDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("parameters-file", Library.Interface.CommandLineArgument.ArgumentType.Path, Strings.Program.ParametersFileOptionShort, Strings.Program.ParametersFileOptionLong2, "", new string[] {"parameter-file", "parameterfile"}),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("portable-mode", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Boolean, Strings.Program.PortablemodeCommandDescription, Strings.Program.PortablemodeCommandDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("log-file", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Path, Strings.Program.LogfileCommandDescription, Strings.Program.LogfileCommandDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("log-level", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Enumeration, Strings.Program.LoglevelCommandDescription, Strings.Program.LoglevelCommandDescription, "Warning", null, Enum.GetNames(typeof(Duplicati.Library.Logging.LogMessageType))),
|
||||
new Duplicati.Library.Interface.CommandLineArgument(WebServerLoader.OPTION_WEBROOT, Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Path, Strings.Program.WebserverWebrootDescription, Strings.Program.WebserverWebrootDescription, WebServerLoader.DEFAULT_OPTION_WEBROOT),
|
||||
new Duplicati.Library.Interface.CommandLineArgument(WebServerLoader.OPTION_PORT, Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.WebserverPortDescription, Strings.Program.WebserverPortDescription, WebServerLoader.DEFAULT_OPTION_PORT.ToString()),
|
||||
new Duplicati.Library.Interface.CommandLineArgument(WebServerLoader.OPTION_SSLCERTIFICATEFILE, Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.WebserverCertificateFileDescription, Strings.Program.WebserverCertificateFileDescription, WebServerLoader.OPTION_SSLCERTIFICATEFILE),
|
||||
new Duplicati.Library.Interface.CommandLineArgument(WebServerLoader.OPTION_SSLCERTIFICATEFILEPASSWORD, Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.WebserverCertificatePasswordDescription, Strings.Program.WebserverCertificatePasswordDescription, WebServerLoader.OPTION_SSLCERTIFICATEFILEPASSWORD),
|
||||
new Duplicati.Library.Interface.CommandLineArgument(WebServerLoader.OPTION_INTERFACE, Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.WebserverInterfaceDescription, Strings.Program.WebserverInterfaceDescription, WebServerLoader.DEFAULT_OPTION_INTERFACE),
|
||||
new Duplicati.Library.Interface.CommandLineArgument(WebServerLoader.OPTION_WEBSERVICE_PASSWORD, Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Password, Strings.Program.WebserverPasswordDescription, Strings.Program.WebserverPasswordDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument(WebServerLoader.OPTION_WEBSERVICE_ALLOWEDHOSTNAMES, Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.WebserverAllowedhostnamesDescription, Strings.Program.WebserverAllowedhostnamesDescription, null, [WebServerLoader.OPTION_WEBSERVICE_ALLOWEDHOSTNAMES_ALT]),
|
||||
new Duplicati.Library.Interface.CommandLineArgument(WebServerLoader.OPTION_WEBSERVICE_RESET_JWT_CONFIG, Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Boolean, Strings.Program.WebserverResetJwtConfigDescription, Strings.Program.WebserverResetJwtConfigDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("ping-pong-keepalive", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Boolean, Strings.Program.PingpongkeepaliveShort, Strings.Program.PingpongkeepaliveLong),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("log-retention", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Timespan, Strings.Program.LogretentionShort, Strings.Program.LogretentionLong, DEFAULT_LOG_RETENTION),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("server-datafolder", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Path, Strings.Program.ServerdatafolderShort, Strings.Program.ServerdatafolderLong(DATAFOLDER_ENV_NAME), System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Library.AutoUpdater.AutoUpdateSettings.AppName)),
|
||||
|
||||
});
|
||||
|
||||
return lst.ToArray();
|
||||
}
|
||||
}
|
||||
=> [
|
||||
new Duplicati.Library.Interface.CommandLineArgument("tempdir", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Path, Strings.Program.TempdirShort, Strings.Program.TempdirLong, System.IO.Path.GetTempPath()),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("help", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Boolean, Strings.Program.HelpCommandDescription, Strings.Program.HelpCommandDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("parameters-file", Library.Interface.CommandLineArgument.ArgumentType.Path, Strings.Program.ParametersFileOptionShort, Strings.Program.ParametersFileOptionLong2, "", ParameterFileOptionStrings),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("portable-mode", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Boolean, Strings.Program.PortablemodeCommandDescription, Strings.Program.PortablemodeCommandDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("log-file", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Path, Strings.Program.LogfileCommandDescription, Strings.Program.LogfileCommandDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("log-level", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Enumeration, Strings.Program.LoglevelCommandDescription, Strings.Program.LoglevelCommandDescription, "Warning", null, Enum.GetNames(typeof(Duplicati.Library.Logging.LogMessageType))),
|
||||
new Duplicati.Library.Interface.CommandLineArgument(WebServerLoader.OPTION_WEBROOT, Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Path, Strings.Program.WebserverWebrootDescription, Strings.Program.WebserverWebrootDescription, WebServerLoader.DEFAULT_OPTION_WEBROOT),
|
||||
new Duplicati.Library.Interface.CommandLineArgument(WebServerLoader.OPTION_PORT, Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.WebserverPortDescription, Strings.Program.WebserverPortDescription, WebServerLoader.DEFAULT_OPTION_PORT.ToString()),
|
||||
new Duplicati.Library.Interface.CommandLineArgument(WebServerLoader.OPTION_SSLCERTIFICATEFILE, Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.WebserverCertificateFileDescription, Strings.Program.WebserverCertificateFileDescription, WebServerLoader.OPTION_SSLCERTIFICATEFILE),
|
||||
new Duplicati.Library.Interface.CommandLineArgument(WebServerLoader.OPTION_SSLCERTIFICATEFILEPASSWORD, Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.WebserverCertificatePasswordDescription, Strings.Program.WebserverCertificatePasswordDescription, WebServerLoader.OPTION_SSLCERTIFICATEFILEPASSWORD),
|
||||
new Duplicati.Library.Interface.CommandLineArgument(WebServerLoader.OPTION_INTERFACE, Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.WebserverInterfaceDescription, Strings.Program.WebserverInterfaceDescription, WebServerLoader.DEFAULT_OPTION_INTERFACE),
|
||||
new Duplicati.Library.Interface.CommandLineArgument(WebServerLoader.OPTION_WEBSERVICE_PASSWORD, Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Password, Strings.Program.WebserverPasswordDescription, Strings.Program.WebserverPasswordDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument(WebServerLoader.OPTION_WEBSERVICE_ALLOWEDHOSTNAMES, Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.WebserverAllowedhostnamesDescription, Strings.Program.WebserverAllowedhostnamesDescription, null, [WebServerLoader.OPTION_WEBSERVICE_ALLOWEDHOSTNAMES_ALT]),
|
||||
new Duplicati.Library.Interface.CommandLineArgument(WebServerLoader.OPTION_WEBSERVICE_RESET_JWT_CONFIG, Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Boolean, Strings.Program.WebserverResetJwtConfigDescription, Strings.Program.WebserverResetJwtConfigDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("ping-pong-keepalive", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Boolean, Strings.Program.PingpongkeepaliveShort, Strings.Program.PingpongkeepaliveLong),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("log-retention", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Timespan, Strings.Program.LogretentionShort, Strings.Program.LogretentionLong, DEFAULT_LOG_RETENTION),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("server-datafolder", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Path, Strings.Program.ServerdatafolderShort, Strings.Program.ServerdatafolderLong(DATAFOLDER_ENV_NAME), System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Library.AutoUpdater.AutoUpdateSettings.AppName)),
|
||||
];
|
||||
|
||||
private static bool ReadOptionsFromFile(string filename, ref Library.Utility.IFilter filter, List<string> cargs, Dictionary<string, string> options)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user