NextCloud Let's Encrypt (nginx)

Joined
Jan 6, 2019
Messages
2
Hi Colleagues,

I am new to the FreeNAS Community and I am asking you to help me to validate if I did my HTTPS configuration for NextCloud (11.2-RELEASE-p7) right. I did several hours of research and could not find a solution that helped me in my configuration (NextCloud/nginx/let's encrypt) so I need some Input if I did it the "right way". From my perspective everything is working like expected (site is called via https / certificate is shown as valid in browser, ...)

Preparation Steps:
  1. I installed NextCloud from the Plugins
  2. I adjusted the NextClouds Jail /etc/ssh/sshd_config and adjusted the line PermitRootLogin yes
  3. I changed the root password within the Jail with passwd and started ssh once service sshd onestart
  4. I used putty to ssh into the Nextcloud Jail
Installing Let's Encrypt:
  1. Temporarily allow Jail to get FreeBSD Repositories ee /usr/local/etc/pkg/repos/FreeBSD.conf and adjust line FreeBSD: { enabled: no } to FreeBSD: { enabled: yes }
  2. Install let's encrypt pkg install py27-certbot and follow instructions
  3. I set webroot to /usr/local/www/nextcloud
  4. I got the message: IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at:
    /usr/local/etc/letsencrypt/live/xx.duckdns.org/fullchain.pem
    Your key file has been saved at:
    /usr/local/etc/letsencrypt/live/xx.duckdns.org/privkey.pem
nginx Adjustments:
  1. Edit nextcloud.conf ee /usr/local/etc/nginx/conf.d/nextcloud.conf
  2. Change/Add following Parameters:
    server {
    listen 443;
    ssl on;
    ssl_certificate "/usr/local/etc/letsencrypt/live/xx.duckdns.org/fullchain.pem";
    ssl_certificate_key "/usr/local/etc/letsencrypt/live/xx.duckdns.org/privkey.pem";
    ...
Automatic Certificate Renewal [not yet tested]
  1. Testing the renewal with a dry run: certbot renew --dry-run
  2. SSH into your FreeNAS and run the command jls - this will show you the JID (Jail ID), in my case it was ID=8
  3. Go to the FreeNAS WebGUI and add a monthly cron job that renews the certificate and restarts nginx
    jexec 8 certbot renew --quiet --rsa-key-size 4096 && jexec 8 service nginx reload
I would really appreciate if you can give me feedback as my goal would be to operate a safe NextCloud Environment within the Internet.

regards,
Joe

Sources:
-----------
FreeNAS-11.2-RELEASE-U1
Intel(R) Celeron(R) CPU G3900 @ 2.80GHz (2 cores)
16 GiB
 

garm

Wizard
Joined
Aug 19, 2017
Messages
1,555
Joined
Jan 6, 2019
Messages
2
Hi garm,

Thanks for welcoming&your fast answer :) The links you posted are very helpful!

I thought about putting the NextCloud Instance into the DMZ but then decided for the moment to leave it in my LAN simply do a port forwarding for 443 to the NextCloud instance (Firewall is installed). From networking engineering perspective I have some Room for Improvements that I am aware of (I am thinking about a firewalled solution with different subnets or VLANs e.g. DMZ, IoT Devices, ...).

I installed NextCloud/nginx with the standard "Packet/Plugin" that is delivered by the WebGui, when I reviewed the nginx settings they already seemed to be hardened to some part.. but I will take that as a task with me to optimize the hardening
 
Last edited:

EGP

Dabbler
Joined
Jan 6, 2017
Messages
18
Great write up! I have ssh enabled to FreeNAS so I just ran the commands inside the jail with success! scan.nextcloud.com gave the installation an A+! I also forward port 443 through my firewall. Only other thing was I had to stop nginx to run certbot. '/usr/local/etc/rc.d/nginx stop'
Thanks!
 

marschal

Dabbler
Joined
Oct 18, 2018
Messages
10
  1. SSH into your FreeNAS and run the command jls - this will show you the JID (Jail ID), in my case it was ID=8
  2. Go to the FreeNAS WebGUI and add a monthly cron job that renews the certificate and restarts nginx
    jexec 8 certbot renew --quiet --rsa-key-size 4096 && jexec 8 service nginx reload
I don‘t think this will work, hence jexec or iocage exec has to be run with root priviledges (sudo).
BTW: A more generic way imo to execute a command inside your jail is to do that via iocage exec <jail_name> command. So you can access your jail by its name, no matter which ID it has. But anyway: Requires sudo (needs you password to do so).
BTW2: I don‘t think a service restart of nginx is required (but not sure, at least the documentation of certbot does not require a service restart per se.

I created a cron job inside my jail (user root) as suggested in Certbot - Freebsd Nginx with
Code:
sudo iocage exec <jail_name>        # Connect to your jail (as user root)
crontab -e                          # opens a cron job file for user root

Then copy this into your cron job file and save it:
Code:
0 0,12 * * * certbot renew.              


That‘s it!
 

samuel-emrys

Contributor
Joined
Dec 14, 2018
Messages
136
I wrote a guide a while ago for installing nextcloud with apache and implementing the steps identified in the nextcloud hardening guide, plus a few extras. It's obviously not Nginx, but a number of the hardening procedures are web-server agnostic so perhaps it would be worth including those in your how-to
 

EGP

Dabbler
Joined
Jan 6, 2017
Messages
18
I managed to forget my password for NextCloud and had no email address set. Since it is a BSD jail, the syntax for the command line reset is slightly different than what you'll find on the internet. This is what I used with success in the plugin. Those are back ticks!

su -m www -c php\ ``/usr/local/www/nextcloud/occ\ "user:resetpassword username"``

/Thanks post install script!
 

Frederic996

Dabbler
Joined
Oct 13, 2017
Messages
32
Hello everyone, following the guide I have activated https on my nextcloud, but visiting my address I always display an unsafe site warning. why does this happen?
 

gt2416

Patron
Joined
Feb 4, 2018
Messages
262
Hello everyone, following the guide I have activated https on my nextcloud, but visiting my address I always display an unsafe site warning. why does this happen?

Does this happen only on your lan ? Try accessing it from outside your network.
 

Jailer

Not strong, but bad
Joined
Sep 12, 2014
Messages
4,974
I don‘t think this will work, hence jexec or iocage exec has to be run with root priviledges (sudo).
BTW: A more generic way imo to execute a command inside your jail is to do that via iocage exec <jail_name> command. So you can access your jail by its name, no matter which ID it has. But anyway: Requires sudo (needs you password to do so).
BTW2: I don‘t think a service restart of nginx is required (but not sure, at least the documentation of certbot does not require a service restart per se.

I created a cron job inside my jail (user root) as suggested in Certbot - Freebsd Nginx with
Code:
sudo iocage exec <jail_name>        # Connect to your jail (as user root)
crontab -e                          # opens a cron job file for user root

Then copy this into your cron job file and save it:
Code:
0 0,12 * * * certbot renew.             


That‘s it!
You will need to restart nginx to pick up the new cert.

The other option to this is to create a script in the root of the jail and set a cron task in the FreeNAS web ui to run it. That's how I set mine up and it works. I also have the Hide Standard Errors unchecked so I get an "error" email so I know it's still running. When the certificate renews nginx restarts and generates an "error" and I get an email.
 

Frederic996

Dabbler
Joined
Oct 13, 2017
Messages
32
Hello and thanks for the reply, I have already specified my site and my public ip, but when I visit my cloud I keep on seeing unsafe page .. can I do anything else?

'trusted_domains' =>
array (
0 => '192.168.1.83',
1 => '2.x.x.x', <---My pubblic ip
),
'datadirectory' => '/usr/local/www/nextcloud/data',
 

danb35

Hall of Famer
Joined
Aug 16, 2011
Messages
15,456
Hello and thanks for the reply, I have already specified my site and my public IP, but when I visit my cloud I keep on seeing unsafe page .. can I do anything else?
The Let's Encrypt cert is for a FQDN, not for an IP address. Therefore, if you're visiting the IP address, you'll get an error.
 

EGP

Dabbler
Joined
Jan 6, 2017
Messages
18
I updated the plugin today from the FreeNAS shell. "iocage update nextcloud". After the update completed, my jail was turned off. I powered the jail back on and went to the Installed plugins area and selected management from the menu on the far right. The resulting browser window had a button to finish the web updater. Then I went to the shell of the jail and I re-entered the ssl information from the instructions above and restarted the jail. Everything works as before.
 

jov

Cadet
Joined
Jul 1, 2019
Messages
2
Hey! I've made a little guide based on yours. I needed to also fix:
"PHP does not seem to be setup properly to query system environment variables. The test with getenv(“PATH”) only returns an empty response.
Please check the installation documentation for php configuration notes and the php configuration of your server, especially when using php-fpm. "

& Enabling MySQL 4-byte support


1. Install Nextcloud via FreeNAS Plugins
Keep note of the database login info inside of the installation confirmation dialog
2. Shutdown Jail and add a Mount Point (It's always a good idea to place your Nextcloud data outside of the webroot)
Source = "/mnt/FreeNAS/Nextcloud"
Destination ="/mnt/FreeNAS/iocage/jails/nextcloud/root/mnt"
3. Start up your jail and navigate to your Nextcloud installation. Update the data field to "/mnt"
4. Back in shell run "ee /usr/local/etc/pkg/repos/FreeBSD.conf"
change "FreeBSD: { enabled: no }" -> "FreeBSD: { enabled: yes }"
5. Run "pkg install py27-certbot"
6. Run "certbot certonly" Follow prompts
webroot is "/usr/local/www/nextcloud"

7. Take note of:
"ssl_certificate "/usr/local/etc/letsencrypt/live/x.domain.com/fullchain.pem";
ssl_certificate_key "/usr/local/etc/letsencrypt/live/x.domain.com/privkey.pem";"
8. Run "ee /usr/local/etc/nginx/conf.d/nextcloud.conf" and update
"server {
listen 80;
listen [::]:80;
server_name cloud.jovaniedelacruz.me;
# enforce https
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name cloud.example.com;
ssl_certificate "/usr/local/etc/letsencrypt/live/cloud.jovaniedelacruz.me/fullchain.pem";
ssl_certificate_key "/usr/local/etc/letsencrypt/live/cloud.jovaniedelacruz.me/privkey.pem";
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
..."
9. run "ee /usr/local/www/nextcloud/config/config.php"
add your trusted domain as per entry 0.

10. run "ee /usr/local/etc/php-fpm.d/nextcloud.conf" and add to the bottom
"env[PATH] = /usr/local/bin:/usr/bin:/bin" then run
"service php-fpm restart"
11. run "mysql -u dbadmin -p"
run and check "show variables like 'innodb_file_per_table';" for ON value
If it's ON then run
"ALTER DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;"
and "exit"
12. Should be good! Restart jail for good measaure.


Automatic Certificate Renewal [SEE COMMENT BELOW FOR BETTER IMPLEMENTATION]
Testing the renewal with a dry run: certbot renew --dry-run
SSH into your FreeNAS and run the command "jls" this will show you the JID (Jail ID), in my case it was ID=8
Go to the FreeNAS WebGUI and add a monthly cron job as root that renews the certificate and restarts nginx
jexec 8 certbot renew --quiet --rsa-key-size 4096 && jexec 8 service nginx reload

+ Thanks danb35!

Doing all this yields me a "All checks passed" and an A+ security rating!
 

Attachments

  • Capture.PNG
    Capture.PNG
    16.2 KB · Views: 880
Last edited:

danb35

Hall of Famer
Joined
Aug 16, 2011
Messages
15,456
jexec 8 certbot renew --quiet --rsa-key-size 4096 && jexec 8 service nginx reload
A few points on this:
  • There's no need to specify the key size in this command; it will use whatever it used before.
  • I'd run this daily, not monthly. certbot renew checks the existing cert and only attempts to renew it if it has less than 30 days' validity remaining. If you only run the command monthly, and there's some sort of issue renewing, your cert will expire.
  • Jail numbers change as jails restart and otherwise move; you can (and probably should) use the name instead: jexec nextcloud blah. But better yet to use iocage exec: iocage exec nextcloud certbot renew.
  • You can tell certbot to run a command following issuance/renewal of a script when you initially issue the cert using the --deploy-hook flag
Putting these all together, here's how it would change:
  • The initial command to get the cert would be certbot certonly -w /usr/local/www/nextcloud -d your_fqdn --rsa-key-size 4096 --deploy-hook "service nginx reload" (if there's a reason you really want a 4096-bit key rather than the default of 2048-bit)
  • ...and the daily cronjob would be iocage exec nextcloud certbot renew --quiet
 
  • Like
Reactions: jov

jov

Cadet
Joined
Jul 1, 2019
Messages
2
A few points on this:
  • There's no need to specify the key size in this command; it will use whatever it used before.
  • I'd run this daily, not monthly. certbot renew checks the existing cert and only attempts to renew it if it has less than 30 days' validity remaining. If you only run the command monthly, and there's some sort of issue renewing, your cert will expire.
  • Jail numbers change as jails restart and otherwise move; you can (and probably should) use the name instead: jexec nextcloud blah. But better yet to use iocage exec: iocage exec nextcloud certbot renew.
  • You can tell certbot to run a command following issuance/renewal of a script when you initially issue the cert using the --deploy-hook flag
Putting these all together, here's how it would change:
  • The initial command to get the cert would be certbot certonly -w /usr/local/www/nextcloud -d your_fqdn --rsa-key-size 4096 --deploy-hook "service nginx reload" (if there's a reason you really want a 4096-bit key rather than the default of 2048-bit)
  • ...and the daily cronjob would be iocage exec nextcloud certbot renew --quiet
Thanks for improving on that! That makes sense to me. Didn't understand the --deploy-hook but that looks to be the best way to do it.
We'll see how the cert renewal goes in the future.
 

NasKar

Guru
Joined
Jan 8, 2016
Messages
739
Putting these all together, here's how it would change:
  • The initial command to get the cert would be certbot certonly -w /usr/local/www/nextcloud -d your_fqdn --rsa-key-size 4096 --deploy-hook "service nginx reload" (if there's a reason you really want a 4096-bit key rather than the default of 2048-bit)
  • ...and the daily cronjob would be iocage exec nextcloud certbot renew --quiet
So the --deploy-hook in the original certbot command allows it to reload nginx which is needed to allow nginx to be aware of the renewed certificate?
What do you do if you didn't use the --deploy-hook "service nginx reload" when initially issuing the certbot command?
Would you need to create a script that issues the
Code:
iocage exec nextcloud certbot renew --quiet
and on a separate line
Code:
service nginx reload
and run the script from a cronjob from the freenas GUI?
 

danb35

Hall of Famer
Joined
Aug 16, 2011
Messages
15,456
So the --deploy-hook in the original certbot command allows it to reload nginx which is needed to allow nginx to be aware of the renewed certificate?
Correct. --deploy-hook is a command to run after a cert is successfully issued--in this case, we're using it to simply reload the nginx configuration (which will include loading new certs).
What do you do if you didn't use the --deploy-hook "service nginx reload" when initially issuing the certbot command?
Ideally, edit the renewal config file to use it. But failing that, something like what you're suggesting would work, as would the initial solution posted by @jov. But in both cases, you're doing the nginx reload daily, which isn't really optimal. It's not especially harmful either, though.
 
  • Like
Reactions: jov
Top