Odyssee
Odyssee

Reputation: 2463

Nginx if statement on ssl certificates

I was wondering if it is possible to do an if statement on nginx ssl certificates (Or any other part of the configuration)

if ( -f /etc/letsencrypt/live/{domain}/cert.pem ) {
  ssl_certificate /etc/letsencrypt/live/{domain}/cert.pem;
  ssl_certificate_key /etc/letsencrypt/live/{domain}/privkey.pem;
}

This gives the following error:

nginx: [emerg] "ssl_certificate" directive is not allowed here in /etc/nginx/sites-enabled/app.phase.be.conf:7

I have looked in the documentation and on google, and came to the conclusion that this can't be done. It is for rewrites only.

Is there another way to completely ignore the ssl certificates or replace them with a self signed one until Letsencrypt has issued the certificate. It's an automated process, Nginx can reload at any time if it is triggered by another process (modified server block for example)

EDIT:

Thanks to @Chris for pointing out the right direction!

What I eventually did looks something like this, but this is stripped down and simplified.

config = Config().read()
logging.basicConfig(filename=config['settings']['log_file'],
                      filemode='a',
                      format='%(asctime)s [ %(levelname)s ] - %(message)s',
                      datefmt='%m/%d/%Y  %H:%M:%S',
                      level=config['settings']['log_level'])

class NginxHandler(PatternMatchingEventHandler):
    patterns = ["*.conf", "*.cnf"]

    def process(self, event):
        logging.info('PROXY-LISTENER: Vhost configuration has changed reloading Nginx')
        time.sleep(1)
        subprocess.call(['nginx', '-s', 'reload'])

    def on_modified(self, event):
        self.process(event)

    # def on_created(self, event):
    #     self.process(event)

    def on_deleted(self,event):
        self.process(event)

class SslHandler(PatternMatchingEventHandler):
    patterns = ["*.pem", "*.key", "*.crt"]

    def process(self, event):
        logging.info('PROXY-LISTENER: SSL certificate updated, reloading nginx')
        subprocess.call(['nginx', '-s', 'reload'])

    def on_modified(self, event):
        self.process(event)

    # def on_created(self, event):
    #     self.process(event)

    def on_deleted(self,event):
        self.process(event)

logging.info('PROXY-LISTENER: Starting Proxy Listener')
observer = Observer()
observer.schedule(NginxHandler(), path='/etc/nginx/sites-enabled/')
observer.schedule(SslHandler(), path='/etc/nginx/ssl/', recursive=True)
observer.start()
logging.info('PROXY-LISTENER: Nginx vhost watcher started')
logging.info('PROXY-LISTENER: Nginx certificate watcher started')

This watches two directories on changed and execute an action accordingly. On creation of a new vhost Ssl().add_temp_cert() gets called and creates the needed symbolic links.

def add_temp_cert(self, vhost):
    '''
    Create a symbolic link to provide a temporary ssl certificate 
    for the new vhost untill a valid one has been installed
    '''
        subprocess.call(['mkdir', '-p', '/etc/nginx/ssl/' + self.domain])
        subprocess.call(['ln', '-s', '/etc/nginx/ssl/nginx.crt', '/etc/nginx/ssl/' + domain + '/cert.pem'])
        subprocess.call(['ln', '-s', '/etc/nginx/ssl/nginx.key', '/etc/nginx/ssl/' + domain + '/privkey.pem'])
    else:
        self.add_cert(vhost)

def add__letsencrypt_cert(self, vhost):
    '''
    Create a symbolic link to /etc/nginx/ssl for the obtained ssl certificate
    '''
        subprocess.call(['rm', '-f', '/etc/nginx/ssl/' + self.domain + '/'])
        subprocess.call(['ln', '-s', '/etc/letsencrypt/live/' + self.domain + '/', '/etc/nginx/ssl/' + self.domain + '/'])

Upvotes: 2

Views: 5274

Answers (2)

jsha
jsha

Reputation: 652

Just hardcode some default self-signed certificates, and allow Certbot's Nginx plugin to rewrite the ssl_certificate statements when you run it. For instance, Ubuntu and Debian generate a self-signed "snakeoil" key and certificate by default:

ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate /etc/ssl/private/ssl-cert-snakeoil.key;

If you run certbot by itself, it should detect Nginx and offer to auto-configure Nginx for you. You can also use --nginx to explicitly specify you want to use Nginx autoconfiguration.

Upvotes: 0

anthumchris
anthumchris

Reputation: 9090

If you already an existing process/script that triggers nginx reloads, then use linux symbolic links

server {
  ...

  ssl_certificate      /etc/nginx/ssl/link-cert.pem;
  ssl_certificate_key  /etc/nginx/ssl/link-privkey.pem;

  ...
}

nginx-ssl-reload.sh

#!/bin/bash

# exit on errors
set -e

# remove existing links
rm /etc/nginx/ssl/link-cert.pem
rm /etc/nginx/ssl/link-privkey.pem

DOMAIN="anthum.com"
# link files specified in nginx.conf to real cert files
if [ -f "/etc/letsencrypt/live/$DOMAIN/cert.pem" ]; then
  ln -s "/etc/letsencrypt/live/$DOMAIN/cert.pem"    /etc/nginx/ssl/link-cert.pem
  ln -s "/etc/letsencrypt/live/$DOMAIN/privkey.pem" /etc/nginx/ssl/link-privkey.pem
else
  ln -s /etc/nginx/ssl/self-signed.crt  /etc/nginx/ssl/link-cert.pem
  ln -s /etc/nginx/ssl/self-signed.key  /etc/nginx/ssl/link-privkey.pem
fi


# Reload nginx
nginx -s reload

Upvotes: 7

Related Questions