*New 11.3 series Release:
2019-10-05: XigmaNAS 11.3.0.4.6928 - released, 11.2 series are soon unsupported!

*New 12.0 series Release:
2019-10-05: XigmaNAS 12.0.0.4.6928 - released!

*New 11.2 series Release:
2019-09-23: XigmaNAS 11.2.0.4.6881 - released!

We really need "Your" help on XigmaNAS https://translations.launchpad.net/xigmanas translations. Please help today!

Producing and hosting XigmaNAS costs money. Please consider donating for our project so that we can continue to offer you the best.
We need your support! eg: PAYPAL

[HowTo] Embedded N4F auto renew SSL certs + web UI + syncthing UI

Only Admin's or Moderators can move thread's to this sub-forum.
Nobody should start a new thread on this sub-forum.
Anybody can reply to a thread on this sub-forum.
Forum rules
Set-Up GuideFAQsForum Rules
Post Reply
faust
NewUser
NewUser
Posts: 4
Joined: 20 Jan 2017 03:52
Status: Offline

[HowTo] Embedded N4F auto renew SSL certs + web UI + syncthing UI

#1

Post by faust » 04 Oct 2017 19:28

I wanted to use acme.sh (https://github.com/Neilpang/acme.sh) to generate my internal SSL certificates with Let's Encrypt using the ACME protocol. I also wanted to automate the renewal said certs and use them with the web UI (lighttpd) and with the syncthing UI on my embedded N4F system. I've summarized my method below. The rough procedure is as follows:

- Installing packages on embedded system
- Meeting prereqs for acme.sh
- Running acme.sh and scheduling with cron
- Importing the certs for the web UI and syncthing

Firstly, acme.sh requires wget or curl so making packages persistent on an embedded system is required. Several tutorials describe using unionfs to manage this process which I've followed. I have an encrypted UFS partition called "sysdata" which holds this kind of files. So on the sysdata partition, I created empty /usr/local and /var/db/pkg paths so, once sysdata is mounted, the paths are:

Code: Select all

/mnt/sysdata/unionfs/usr/local
/mnt/sysdata/unionfs/var/db/pkg

Note that there are some reported issues in other threads when using unionfs in this way. From what I've read, these problems are caused by mounting on /var only (rather than the full /var/db/pkg path). Apparently all that is needed in /var is the pkg databases (as /var/db/pkg/local.sqlite appears to maintain information about installed packages). I do have similar concerns about mounting all of /usr/local as, for instance, /usr/local/www is the lighttpd document root and thus contains all of the files for the web UI. So a fair caution is given to the reader on this point.

The unionfs paths are mounted with a postinit script:

Code: Select all

#!/bin/bash

mount_unionfs -o w /mnt/sysdata/unionfs/usr/local /usr/local
mount_unionfs -o w /mnt/sysdata/unionfs/var/db/pkg /var/db/pkg
mount_unionfs -o w /mnt/sysdata/unionfs/acme /home/acme

This runs immediately after my postinit script which mounts my encrypted volumes (further details: viewtopic.php?f=67&t=11930). Note that I also use unionfs to mount an acme home directory (more on that shortly).

After mounting the /usr/local and /var/db/pkg paths with unionfs as per the postinit script, I installed wget with the following commands:

Code: Select all

pkg update
pkg search wget
pkg install wget-1.19.1

I created an unprivileged user, acme, to run acme.sh which does all of its work in the users home directory. Since I keep such system data on encrypted volumes, I once again used unionfs to mount the acme users home directory. This allows me to keep these files encrypted without changing how I use/partition sysdata and provides some logical consistency with how I manage persistence of certain files.

After that, I logged in with the acme user, ran acme.sh using wget (as per the instructions on the github page) and generated certs according to my specification. Since acme.sh supports the DNS API of my (crappy) registrar, that's how I generate my certs. As per the following script:

Code: Select all

#!/bin/bash

ACME_WD=/mnt/sysdata/acme/.acme.sh/
CERT_HN=hostname.domain.tld

$ACME_WD/acme.sh --issue --dns dns_gd -d $CERT_HN --force

I set this script to run with cron (web UI: System > Advanced > Cron), as the acme user every 2 months (Let's Encrypt certs expire after 90 days).

The only thing that remains is copying the cert/key over so that they're used by services of interest. In this case, by lighttpd (for the web UI), and syncthing (for its own web UI).

After some digging through the guts of the web UI, I found that /etc/inc/config.inc and /etc/inc/util.inc had what I needed to deploy the cert. This next PHP script reads the cert and key generated by acme.sh, checks their validity and, if new, saves them to the config file and over the syncthing https cert and key. It then restarts lighttpd and syncthing.

Code: Select all

#!/usr/local/bin/php

<?php

require_once 'config.inc';

# Paths to acme files
$acme_path = "/home/acme/.acme.sh/";
$acme_domain = "hostname.domain.tld";
$acme_cert_path = "{$acme_path}{$acme_domain}/{$acme_domain}.cer";
$acme_key_path = "{$acme_path}{$acme_domain}/{$acme_domain}.key";

# Read the acme cert
$acme_file = fopen($acme_cert_path, "r");
$acme_cert = fread($acme_file, filesize($acme_cert_path));
fclose($acme_file);

# Read the acme key
$acme_file = fopen($acme_key_path, "r");
$acme_key = fread($acme_file, filesize($acme_key_path));
fclose($acme_file);

# Check validity of cert and key
$valid_cert = is_valid_certificate($acme_cert);
$valid_key = is_valid_privatekey($acme_key,"RSA");

# Check if cert and key are new
$isnew_cert = (base64_encode($acme_cert) != $config['system']['webgui']['certificate']);

# Import cert if cert/key are valid and cert is new
if ($valid_cert && $valid_key && $isnew_cert):

	echo "PHP acme cert import: Importing new certificate..." . PHP_EOL;
	echo " - $acme_cert_path" . PHP_EOL;

	# Write cert to config
	$config['system']['webgui']['certificate'] = base64_encode($acme_cert);
	echo " - $acme_key_path" . PHP_EOL;

	# Write key to config
	$config['system']['webgui']['privatekey'] = base64_encode($acme_key);
	echo " - Writing to config.xml" . PHP_EOL;

	# Commit to config file
	write_config();

	# Syncthing: copy certs and restart
	echo " - Copying cert/key to syncthing directory" . PHP_EOL;
	exec("cp {$acme_path}{$acme_domain}/{$acme_domain}.cer {$syncthing_dir}https-cert.pem");
	exec("cp {$acme_path}{$acme_domain}/{$acme_domain}.key {$syncthing_dir}https-key.pem");
	exec("chown syncthing:syncthing {$syncthing_dir}https-cert.pem");
	exec("chown syncthing:syncthing {$syncthing_dir}https-key.pem");
	echo " - Restarting syncthing" . PHP_EOL;
	exec("service syncthing stop");
	exec("service syncthing onestart");

	# Restart lighttpd
	echo " - Restarting lighttpd" . PHP_EOL;
	exec("/etc/rc.d/lighttpd restart");

# Don't import cert if invalid or isn't new
else:
	echo "PHP acme cert import: Not importing cert/key." . PHP_EOL;
	if (!$valid_cert): echo " - Invalid certificate : $acme_cert_path" . PHP_EOL; endif;
	if (!$valid_key): echo " - Invalid private key : $acme_key_path" . PHP_EOL; endif;
	if (!$isnew_cert): echo " - Certificate already in use : $acme_cert_path" . PHP_EOL; endif;
endif;

?>

I set this script up with cron to run as root every week. This means that roughly 90% of the time, it just looks at the same old certs, notes that they haven't changed, and does nothing.

When lighttpd is started, the rc.d script copies the SSL cert and key (if applicable) directly from the config file and saves them to /var/etc/cert.pem. This means that the cert/key can't simply be copied to the correct location followed by a restart of lighttpd. Also, if the cert/key is entered in the web UI manually and saved, the new cert is not loaded and the user is prompted that a restart is required (in order to restart lighttpd). This avoids the need for a restart.

Note that syncthing is started with the "onestart" argument instead of "start" because I don't have syncthing enabled in the config file. Since my syncthing system files are stored on an encrypted UFS partition, I start syncthing manually with a postinit script after all encrypted partitions (and unionfs directories) are mounted and stop it manually with a shutdown script before unmounting all such systems.

User avatar
tony1
Moderator
Moderator
Posts: 172
Joined: 14 Jul 2016 19:04
Status: Offline

Re: [HowTo] Embedded N4F auto renew SSL certs + web UI + syncthing UI

#2

Post by tony1 » 08 Oct 2017 15:07

you could probably set the cert location using the "Additional Parameters" section of the webserver.
just an idea?

User avatar
jerryone
Starter
Starter
Posts: 59
Joined: 22 Sep 2017 21:45
Location: Timisoara
Contact:
Status: Offline

Re: [HowTo] Embedded N4F auto renew SSL certs + web UI + syncthing UI

#3

Post by jerryone » 17 Dec 2017 14:27

hmm, it is possible to make a video tutorial of what is in here? i have tray to do this in a virtual machines and the result was not what i have expected. may i have jump steps, but i have tray two times and nothing happend with this SSL cert install. i am quite a new to this kind off line write and freebsd servers!!! thanks ! or i don't know may by click on this after u see this click and copy this... for the stupid guys that are tray to do and understand! many thanks !
Dell T610 Xeon x5650 x2 , 192 GB DELL ECC, HBA 9211-8i LSI x2 , 7xHGST-4TB, 2xSamsung 1TB, , 1xKingston 128GB-SSD boot sys
CIFS/SMB, Syncthing, DLNA/UPnP MiniDLNA, BitTorrent, Plex Media Server

User avatar
raulfg3
Site Admin
Site Admin
Posts: 4921
Joined: 22 Jun 2012 22:13
Location: Madrid (ESPAÑA)
Contact:
Status: Offline

Re: [HowTo] Embedded N4F auto renew SSL certs + web UI + syncthing UI

#4

Post by raulfg3 » 17 Dec 2017 18:06

ideally, this procedure must be installed by OBI to share it with all users.

any volunteers?.
12.0.0.4 (revision 6766)+OBI on SUPERMICRO X8SIL-F 8GB of ECC RAM, 12x3TB disk in 3 vdev in RaidZ1 = 32TB Raw size only 22TB usable

Wiki
Last changes

sherman
Starter
Starter
Posts: 41
Joined: 27 Dec 2014 15:16
Status: Offline

Re: [HowTo] Embedded N4F auto renew SSL certs + web UI + syncthing UI

#5

Post by sherman » 14 Mar 2018 10:38

Let's Encrypt is such a great additon to the world of the Internet.
But I wonder why there is so less enthusiam here in the forum about it. Rarely thread or tutorial like this one.
Is Nas4free more or less a dead project and only for nerds?
It would be so nice if normal dads coudl benefit from Nas4Free and an easy way to use auto updating SSL certs.
Obi ?

User avatar
raulfg3
Site Admin
Site Admin
Posts: 4921
Joined: 22 Jun 2012 22:13
Location: Madrid (ESPAÑA)
Contact:
Status: Offline

Re: [HowTo] Embedded N4F auto renew SSL certs + web UI + syncthing UI

#6

Post by raulfg3 » 14 Mar 2018 11:18

+1 to add to OBI.

But actually there are a few developers and are focused on other things.
12.0.0.4 (revision 6766)+OBI on SUPERMICRO X8SIL-F 8GB of ECC RAM, 12x3TB disk in 3 vdev in RaidZ1 = 32TB Raw size only 22TB usable

Wiki
Last changes

hc221
Starter
Starter
Posts: 17
Joined: 03 Sep 2015 12:01
Status: Offline

Re: [HowTo] Embedded N4F auto renew SSL certs + web UI + syncthing UI

#7

Post by hc221 » 14 Mar 2018 16:37

Hey Guys, I made a setup with virtualbox and a Ubuntu nginx Server in there. On this way it was easy to implement letsencrypt to a dedicated Server which has no impact on local nas4free setup. Could be a solution.

User avatar
HenriM
Starter
Starter
Posts: 56
Joined: 15 Jun 2013 12:17
Location: Rijsbergen, The Netherlands
Contact:
Status: Offline

Re: [HowTo] Embedded N4F auto renew SSL certs + web UI + syncthing UI

#8

Post by HenriM » 01 Feb 2019 16:27

+1

It would be nice that you can 'just' configure a file-location to the Certificate and Private Key. This way you would only need to update this file-location for e.g. the Let's Encrypt certificates. In case XigmaNAS detects a difference it knows that it should restart the web-server (without need of completely restarting the whole server).

Small side-note. Just found out that for private key you need next header/footer:

-----BEGIN RSA PRIVATE KEY-----
-----BEGIN END PRIVATE KEY-----

Mind the RSA part which is normally not present in the private key of Let's Encrypt. This should thus also be taken into account.

Post Reply

Return to “[HowTo]”