ohadschn / letsencrypt-webapp-renewer

[PLEASE USE FREE MS MANAGED CERTS INSTEAD] Simple WebJob-ready console application for renewing Azure Web App SSL certificates
https://www.ohadsoft.com/
Apache License 2.0
282 stars 51 forks source link

Default webRootPath for linux based webapps is incorrect/undocumented. #87

Closed profet23 closed 5 years ago

profet23 commented 5 years ago

When targeting Linux based asp.net core web apps the default webRootPath puts the .well-known/acme-challenge directory in:

/home/site/wwwroot

When it actually needs to be in:

/home/site/wwwroot/wwwroot

I couldn't get this to work by setting webRootPath to the full path. But by using the following relative path, it seems to be working fine.

./site/wwwroot/wwwroot

Just putting this here to save someone a few hours of debugging and some letsencrypt rate limiting... /sigh

ohadschn commented 5 years ago

Thank you for the information.

  1. Would you mind submitting a PR to fix the docs?
  2. I suggest you work against the Let's Encrypt staging endpoint to avoid rate limits.
CodeBlanch commented 3 years ago

I had a difficult time getting this working for a .NET 5.0 app being deployed to Azure App Service in a Linux container. Posting what I had to do here for anyone else that might come across this.

1) For the web job set webRootPath to ./acme. This ends up /home/acme. Eg: letsencrypt:appname-webRootPath=./acme The guide says to use ./site/wwwroot/wwwroot but both ContentRootPath (./site/wwwroot) and WebRootPath (./site/wwwroot/wwwroot) were ending up as read-only inside the container. /home seems visible and writable.

2) I added this IApplicationBuilder extension based on Hammad Ahmad's blog:

        private const string WellKnownFolder = ".well-known";
        private const string WellKnownRequestPath = "/.well-known";
        private const string WellKnownContentType = "text/plain";

        /// <summary>
        /// Adds ACME challenge static file support into an application's startup configuration.
        /// </summary>
        /// <param name="builder"><see cref="IApplicationBuilder"/> being configured.</param>
        /// <param name="acmeRootPath">Root folder for ACME challenge files. Default value: <see cref="IWebHostEnvironment.WebRootPath"/>.</param>
        /// <returns>Supplied <see cref="IApplicationBuilder"/> for chaining.</returns>
        public static IApplicationBuilder UseAcmeChallengeStaticFiles(this IApplicationBuilder builder, string? acmeRootPath = null)
        {
            if (builder == null)
                throw new ArgumentNullException(nameof(builder));

            if (string.IsNullOrEmpty(acmeRootPath))
            {
                acmeRootPath = builder.ApplicationServices.GetRequiredService<IWebHostEnvironment>().WebRootPath;
            }

            string acmeChallengeWellKnownFolderPath = $"{acmeRootPath}{Path.DirectorySeparatorChar}{WellKnownFolder}";
            if (!Directory.Exists(acmeChallengeWellKnownFolderPath))
                Directory.CreateDirectory(acmeChallengeWellKnownFolderPath);

            return builder
                .UseStaticFiles(new StaticFileOptions
                {
                    RequestPath = WellKnownRequestPath,
                    FileProvider = new PhysicalFileProvider(acmeChallengeWellKnownFolderPath),
                    ServeUnknownFileTypes = true,
                    DefaultContentType = WellKnownContentType
                });
        }

3) Then register that in startup:

        public void Configure(IApplicationBuilder app, IConfiguration config)
        {
            app.UseAcmeChallengeStaticFiles(config.GetValue<string?>("AcmeChallengeRootFolder", null));
            app.UseStaticFiles();
        }

4) Hooked up to a config setting for convenience:

{
   "AcmeChallengeRootFolder": "/home/acme",
}

Working for me!