1

I have a containerized apache setup that needs to optionally enable SSL if the cert file was mapped in. I have this working for the case of when the cert files are mapped in, but struggling with the right directive to only optionally have it enabled.

Given being a containerized app, it makes it harder to just edit this file in production. Wondering if having an additional environment variable to enable the ssl is the way to go, but this seems like the more elegant route?

000-default.conf:

<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

<If "-f '/etc/oqm/certs/systemCert.crt'">
Define SSL_CERT_FILE_PROVIDED 1
</If>
<IfDefine SSL_CERT_FILE_PROVIDED>
    <VirtualHost *:443>
            SSLEngine on
            SSLCertificateFile /etc/oqm/certs/systemCert.crt
            SSLCertificateKeyFile /etc/oqm/certs/systemPrivateKey.pem

            ServerAdmin webmaster@localhost
            DocumentRoot /var/www/html

            ErrorLog ${APACHE_LOG_DIR}/error.log
            CustomLog ${APACHE_LOG_DIR}/access.log combined
    </VirtualHost>
</IfDefine>

Dockerfile for context:

FROM php:8.3-apache
COPY webroot /var/www/html/
COPY 000-default.conf /etc/apache2/sites-available/000-default.conf
#COPY php.ini /usr/local/etc/php/php.ini-development
RUN chown -R www-data:www-data /var/www/html && \
    a2enmod ssl && a2enmod socache_shmcb
EXPOSE 80
EXPOSE 443

As this stands, this ends up with a SSLCertificateFile: file '/etc/oqm/certs/systemCert.crt' does not exist or is empty error. It seems like my understanding of how the If directive works is off, but the Define directive seems to run even when the file is not present. Removing the If directive seems to allow the server to start without the file, but obviously without the option of ssl.

11
  • Why do you want this? What business problem it is supposed to solve? In 2024, it seems more reasonable to not let it start if there is no SSL certificate, since that clearly signifies a misconfiguration. Commented Jun 5 at 5:18
  • Not disagreeing necessarily, but this container could be deployed where a cert is given to it or on a kubernetes style deployment where the ssl termination happens outside of the containerized app, hence needing the optional bit
    – Snappawapa
    Commented Jun 5 at 5:21
  • If it SSL striping happens outside, why ever having any SSL-related configuration inside a container then? Anyway, I think there is no such mechanism in Apache HTTPD, it's just impossible to choose parts of configuration based on existence of some external file. Commented Jun 5 at 5:22
  • 1
    I would suggest that you take care of it and always creating a certificate
    – djdomi
    Commented Jun 5 at 5:26
  • 1
    you could use the snake oil certificate that is mostly delivered by modern distributors and use make-ssl-cert to renew it if been available
    – djdomi
    Commented Jun 5 at 16:16

2 Answers 2

1

According to the Apache documentation:

Directives that take affect during configuration parsing, such as Define, Include, and Error cannot be made conditional by enclosing them in an if configuration section. These sections are always part of the configuration, regardless of how they evaluate at runtime.

Your current approach won't work. You can try to set the certificate configuration directly in the <If> section without defining a variable.

3
  • Alas, that ends up with a <VirtualHost not allowed in <If> context error. But that does explain the behavior
    – Snappawapa
    Commented Jun 5 at 6:39
  • You could try to keep only the SSL directives in the <If> section. Commented Jun 5 at 6:53
  • I tried that too, got basically the same error except SSLEngine not allowed in If
    – Snappawapa
    Commented Jun 5 at 14:53
0

Ethics and best practices debate aside, I landed on the following solution. As Apache has severely limited support for Ifs and related, I ended up handling this in a script that wraps the entry command of the container, and modifies the config file if appropriate:

#!/bin/bash

CONF_FILE="/etc/apache2/sites-available/000-default.conf"
CERT_FILE="/etc/oqm/certs/systemCert.crt"
KEY_FILE="/etc/oqm/certs/systemPrivateKey.pem"

if [ -f "$CERT_FILE" ] && [ -f "$KEY_FILE" ]; then
    echo "Determined have cert files, adjusting config file."
    cat <<EOF >> $CONF_FILE

<VirtualHost *:443>
    SSLEngine on
    SSLCertificateFile $CERT_FILE
    SSLCertificateKeyFile $KEY_FILE

    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html

    ErrorLog \${APACHE_LOG_DIR}/error.log
    CustomLog \${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
EOF
else
   echo "Running without SSL Config.";
fi

apache2-foreground

This then gets copied in, chmod +x, and used as the new start command:

FROM php:8.3-apache
COPY webroot /var/www/html/
COPY containerSrc/000-default.conf /etc/apache2/sites-available/000-default.conf
COPY containerSrc/startup.sh /usr/local/bin/startup.sh
#COPY php.ini /usr/local/etc/php/php.ini-development
RUN chmod +x /usr/local/bin/startup.sh && chown -R www-data:www-data /var/www/html && \
    a2enmod ssl && a2enmod socache_shmcb
# USER www-data
EXPOSE 80 443
CMD ["startup.sh"]

Something to add here would be support for an environment variable to force a check/fail if no ssl certs were present, but this allows me to do what I need for now.

Leaving here for posterity but feel free to tell me I am gross and terrible, and if a better solution arises.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .