Automatic redirect to HTTPS only if on_demand ask gives 200 OK

@francislavoie thank you for your precise and professional response!

I’ve implemented your suggestion and I have a working config:

{
    email myemail@example.com
    on_demand_tls {
        ask https://cfl.man-at-work.it/api/allowed-domain.php
    }
}

(global-encode) {
    encode zstd gzip
}

# add here any known site addresses that need HTTP -> HTTPS redirect
http://cfl.man-at-work.it,
http://other.example.com,
http://anotherone.example.net, {
  redir https://{host}{uri}
}

https://cfl.man-at-work.it {
    import global-encode
    root * /srv/www/cfl/current/public/

    # keep this line to avoid on_demand webhook call on itself
    tls myemail@example.com

    file_server
    php_fastcgi unix//run/php/php7.2-fpm.sock

    log {
        output file /var/log/caddy/cfl.log
    }
}

https://other.example.com,
https://anotherone.example.net {
    import global-encode
    root * /srv/www/static_site/

    # keep this line to avoid on_demand webhook call
    tls myemail@example.com

    file_server
}

# HTTP catch-all that manages HTTPS redirect for good SAAS domains and a generic 404 for all other
http:// {
    import global-encode
    root * /srv/www/sat_check/
    header X-Sat-Checker "Here I am, rock you like a hurricane"
    file_server
    php_fastcgi unix//run/php/php7.2-fpm.sock
}

# HTTPS catch-all with on-demand SSL cert
https:// {
    import global-encode
    tls {
        on_demand
    }

    root * /srv/www/sat/current/public/

    @urlblock {
        path_regexp wpattack /(wp-admin|wp-login|wp-content|xmlrpc|wp|wordpress)
    }
    respond @urlblock 410

    file_server
    php_fastcgi unix//run/php/php7.2-fpm.sock

    log {
        output file /var/log/caddy/sat.log
    }
}

http:// catch all will responds in rpoduction server with a symfony application that convert http request to https after looking up and validating domain name, this is the test file I wrote to outline the process logic:

<?php

$goodDomains = [
    'cfl.man-at-work.it',
    'sat1.man-at-work.it',
    'sat2.man-at-work.it',
    'sat3.man-at-work.it',
];

$domain = $_SERVER['HTTP_HOST'];

if (in_array($domain, $goodDomains, true)) {
    //redirect to https
    $redirectUrl = 'https://' . $domain;
    //rebuild orginal request
    if (strlen($_SERVER['REQUEST_URI']) > 0) {
        $redirectUrl .= $_SERVER['REQUEST_URI'];
    }
    if (strlen($_SERVER['QUERY_STRING']) > 0) {
        $redirectUrl .= '?' . $_SERVER['QUERY_STRING'];
    }

    http_response_code(301);
    header('Location: ' . $redirectUrl);
    die();
}

echo '<html><body>Site not enabled</body></html>';

Both above script and allowed-domain.php in previous post are not actual production code, they both are part of a Symfony application that lookup domain names on a Redis instance, but I agree with you on O(1) vs O(n) algorithms.

I’ve tried this option because I’ve found it in documentation, but Caddy reported an error: I find very strange reading official documentation for an unreleased version of the software, without clear indication that a particular option is available only on a future version.

Apart from this inconvenience with the documentation, I’m glad I started working with Caddy2!

2 Likes