Template help - another syntax error

Once again, I’m sure I’m missing something simple, but I’ve been banging my head against this for a while and not getting anywhere. I’m working on the template fragment for Leanote, and trying to modify it to allow for custom certificate and key files–if $leanote{CertFile} is set to something, include a block setting the cert/chain/key files; if it is empty (or not set at all), don’t include that block. Here’s what I’m working with:

{
my $host = $leanote{hostname} || "leanote";
$OUT .= <<EOF
<VirtualHost *:80>
  ServerName $host.$DomainName
  RewriteEngine on
  RewriteRule ^/\\.well-known/ - [L]
  RewriteRule (.*) https://leanote.$DomainName\$1 [R,L]
  Alias "/.well-known/acme-challenge/" "/var/www/html/.well-known/acme-challenge/"
  <Directory "/var/www/html/.well-known/acme-challenge/">
     Require all granted
     Options -Indexes -FollowSymLinks
     AllowOverride None
  </Directory>
</VirtualHost>

<VirtualHost *:443>
  ServerName $host.$DomainName
  SSLEngine on
  ProxyPass / http://127.0.0.1:9000/
  ProxyPassReverse / http://127.0.0.1:9000/
EOF
if (length $leanote{CertFile}) {
	$OUT .= <<EOF
  SSLCertificateFile $leanote{CertFile}
  SSLCertificateChainFile $leanote{ChainFile}
  SSLCertificateKeyFile $leanote{KeyFile}
EOF
}
$OUT .= "</VirtualHost>\n"
} 

But it keeps dying with an error on the if statement:

ERROR in /etc/e-smith/templates-custom//etc/httpd/conf.d/virtualhosts.conf/15_leanote: Program fragment delivered error <<syntax error at /etc/e-smith/templates-custom//etc/httpd/conf.d/virtualhosts.conf/15_leanote line 23, near ") {"
  (Might be a runaway multi-line << string starting on line 3)>> at template line 1

I’m stumped–I can’t see anything wrong with the if statement, and the heredoc certainly seems to be properly terminated. Adding a blank line after the first EOF gets rid of the “might be a runaway multi-line…” statement, but the error message itself doesn’t change. What am I missing?

EOF and if needs a separation, I know sometimes EOF have some unpredictable behaviour. I prefer to use qq when I have some vars to replace or q if I can display it like this

So

$OUT .= qq (
What you want to $expand
);

If the cert of leanot is not set I would write

If ($leanote{cert}) {
Do something
}

2 Likes

This is how I do with certs, I prefer to use the pki certificate, it is the nethserver default

The default certificate is used, well, by default–if I don’t specify any cert/key in the Virtual Host definition at all, that’s what’s going to be used. The problem with that is that management of lots (really, more than just a handful) of SANs on that cert is cumbersome at best, and Neth really doesn’t do anything to make it any easier–just type in a comma-separated list of everything you want on the cert. Every FQDN, every time. There’s no ability to edit (add to or remove from) the existing list, no ability to point/click to add or remove FQDNs–just type the whole list in, every time. This is tedious with even a very basic installation, if (as many folks do) you want to use different hostnames for different services (www, imap, smtp, pop, ftp, ad, and the base domain are already 7 SANs). And then any time you add or remove a virtual host (or a package that you want to use as a virtual host), you need to do the same thing again, entering the complete list with no errors (because there’s no validation on the user input).

And even ignoring the challenge of managing that cert using the tools Neth gives you (and yes, certbot suffers from this same deficiency, but it could still be done through the GUI), that starts to give you a really big cert. That increases the traffic for each TLS handshake and slows response times (albeit only slightly). It also exposes information about your infrastructure that you might prefer not to be so obvious–maybe you don’t want every visitor to your site to see that you’re also running an internal AD server, or a Nextcloud instance, or whatever*. This issue could be avoided with a wildcard cert, but Neth doesn’t support those either provides no way to obtain those.

Wow, that was a bit of a rant. Anyway, that’s why I’d like users to have the option of setting a custom cert. If they don’t, the default cert is used.

*Not including those SANs in the default cert doesn’t do a whole lot to hide them; the certs will still be logged in transparency logs, so anyone who’s interested can see what certs have been issued for your domain. But at least they have to go looking, rather than getting that information for free with every TLS handshake.

…and I’m getting the same error when I replace the heredoc construction with qq:

[root@neth-test ~]# expand-template /etc/httpd/conf.d/virtualhosts.conf
ERROR in /etc/e-smith/templates-custom//etc/httpd/conf.d/virtualhosts.conf/15_leanote: Program fragment delivered error <<syntax error at /etc/e-smith/templates-custom//etc/httpd/conf.d/virtualhosts.conf/15_leanote line 23, near ") {"
  (Might be a runaway multi-line () string starting on line 3)>> at template line 1

If I add a blank line after the closing paren, the suggestion about the runaway multi-line string goes away, but the error doesn’t change:

[root@neth-test ~]# expand-template /etc/httpd/conf.d/virtualhosts.conf
ERROR in /etc/e-smith/templates-custom//etc/httpd/conf.d/virtualhosts.conf/15_leanote: Program fragment delivered error <<syntax error at /etc/e-smith/templates-custom//etc/httpd/conf.d/virtualhosts.conf/15_leanote line 24, near ") {">> at template line 1

can we read the full file, it is easier to debug and test

Here’s the current version:

{
my $host = $leanote{hostname} || "leanote";
$OUT .= qq (
<VirtualHost *:80>
  ServerName $host.$DomainName
  RewriteEngine on
  RewriteRule ^/\\.well-known/ - [L]
  RewriteRule (.*) https://$host.$DomainName\$1 [R,L]
  Alias "/.well-known/acme-challenge/" "/var/www/html/.well-known/acme-challenge/"
  <Directory "/var/www/html/.well-known/acme-challenge/">
     Require all granted
     Options -Indexes -FollowSymLinks
     AllowOverride None
  </Directory>
</VirtualHost>

<VirtualHost *:443>
  ServerName $host.$DomainName
  SSLEngine on
  ProxyPass / http://127.0.0.1:9000/
  ProxyPassReverse / http://127.0.0.1:9000/
)
if (length $leanote{CertFile}) {
	$OUT .= qq (
  SSLCertificateFile $leanote{CertFile}
  SSLCertificateChainFile $leanote{ChainFile}
  SSLCertificateKeyFile $leanote{KeyFile}
)
}
$OUT .= "</VirtualHost>\n"
}

L22 you missed );

-)
+);

L28 same typo

3 Likes

Like I said:

That seems to have done it, thanks.

1 Like