aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandre Alouit <alexandre.alouit@gmail.com>2015-11-09 02:13:08 +0100
committerAlexandre Alouit <alexandre.alouit@gmail.com>2015-11-09 02:13:08 +0100
commit9ea9794d8b8babae7cb670f8d187f16fbf0ed848 (patch)
tree4320b356ffd01f776b8da5dbd44dd6355b8c5327
parent89b7f0006d34c2d3b37a8aad6a9809eb1955b26f (diff)
first working version
-rw-r--r--README.md65
-rw-r--r--_todo5
-rw-r--r--apache.letsencrypt.conf5
-rw-r--r--cli.ini29
-rw-r--r--cli.ini.patch11
-rw-r--r--install.php165
-rw-r--r--ispconfig.patch466
-rw-r--r--nginx.conf.patch15
8 files changed, 761 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..4ca41ef
--- /dev/null
+++ b/README.md
@@ -0,0 +1,65 @@
+ISPConfig Let's Encrypt
+=========================
+
+
+# REQUIRREMENTS
+
+Let's Encrypt installed
+
+ISPConfig 3.0.5.4p8 or newer
+
+Apache or Nginx
+
+
+# INSTALLATION (as root)
+
+```
+git clone https://github.com/alexalouit/ISPConfig-letsencrypt.git
+cd ISPConfig-letsencrypt
+php -q install.php
+```
+
+After install, a new checkbox will be available in editing website, just check it.
+
+
+## MANUAL INSTALLATION
+
+- patch or create Let's Encrypt configuration
+```
+cp ./cli.ini /etc/letsencrypt/cli.ini
+ or
+patch /etc/letsencrypt/cli.ini < ./cli.ini.patch
+```
+
+- patch ISPConfig
+```
+cp ispconfig.patch /usr/local/ispconfig/ispconfig.patch
+cd /usr/local/ispconfig
+patch -p3 < ./ispconfig.patch
+rm ./ispconfig.patch
+```
+
+- prepare apache
+```
+cp ./apache.letsencrypt.conf /etc/apache2/conf-available/letsencrypt.conf
+a2enmod headers
+a2enconf letsencrypt
+service apache2 reload
+```
+
+- prepare nginx
+```
+patch /etc/nginx/nginx.conf < ./nginx.conf.patch
+service nginx reload
+```
+
+- create a cron for automatic renewal:
+```
+crontab -e
+30 02 * * * /root/.local/share/letsencrypt/bin/letsencrypt-renewer >> /var/log/ispconfig/cron.log; done
+```
+
+- sql queries:
+```
+ALTER TABLE `web_domain` ADD `ssl_letsencrypt` enum('n','y') NOT NULL DEFAULT 'n';
+``` \ No newline at end of file
diff --git a/_todo b/_todo
new file mode 100644
index 0000000..cf2c6a5
--- /dev/null
+++ b/_todo
@@ -0,0 +1,5 @@
+check dns entry is correct before request to Let's Encrypt (apache and nginx plugin)
+check dns MX entry is correct before request to Let's Encrypt (apache and nginx plugin)
+check if we already have a symlink and if he's valid (apache and nginx plugin)
+force ssl field to on when use Let's Encrypt (api access)
+disable ssl tab when use Let's Encrypt (webgui) \ No newline at end of file
diff --git a/apache.letsencrypt.conf b/apache.letsencrypt.conf
new file mode 100644
index 0000000..43ab897
--- /dev/null
+++ b/apache.letsencrypt.conf
@@ -0,0 +1,5 @@
+ <IfModule mod_headers.c>
+ <LocationMatch "/.well-known/acme-challenge/*">
+ Header set Content-Type "application/jose+json"
+ </LocationMatch>
+ </IfModule> \ No newline at end of file
diff --git a/cli.ini b/cli.ini
new file mode 100644
index 0000000..6eab855
--- /dev/null
+++ b/cli.ini
@@ -0,0 +1,29 @@
+# This is an example of the kind of things you can do in a configuration file.
+# All flags used by the client can be configured here. Run Let's Encrypt with
+# "--help" to learn more about the available options.
+
+# Use a 4096 bit RSA key instead of 2048
+rsa-key-size = 4096
+
+# Always use the staging/testing server
+server = https://acme-staging.api.letsencrypt.org/directory
+
+# Uncomment and update to register with the specified e-mail address
+# email = foo@example.com
+
+# Uncomment to use a text interface instead of ncurses
+# text = True
+
+# Uncomment to use the standalone authenticator on port 443
+# authenticator = standalone
+# standalone-supported-challenges = dvsni
+
+# Uncomment to use the webroot authenticator. Replace webroot-path with the
+# path to the public_html / webroot folder being served by your web server.
+# authenticator = webroot
+# webroot-path = /usr/share/nginx/html
+
+text = True
+agree-dev-preview = True
+agree-tos = True
+authenticator = webroot
diff --git a/cli.ini.patch b/cli.ini.patch
new file mode 100644
index 0000000..e038f5c
--- /dev/null
+++ b/cli.ini.patch
@@ -0,0 +1,11 @@
+--- cli.ini 2015-11-06 20:21:09.332000000 +0100
++++ cli.ini 2015-11-06 20:21:27.380000000 +0100
+@@ -22,3 +22,8 @@
+ # path to the public_html / webroot folder being served by your web server.
+ # authenticator = webroot
+ # webroot-path = /usr/share/nginx/html
++
++text = True
++agree-dev-preview = True
++agree-tos = True
++authenticator = webroot
diff --git a/install.php b/install.php
new file mode 100644
index 0000000..f5ef25f
--- /dev/null
+++ b/install.php
@@ -0,0 +1,165 @@
+<?php
+/*
+Let's Encrypt for ISPConfig
+Copyright (c) 2015, Alexandre Alouit <alexandre.alouit@gmail.com>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+$backup_dir = "/var/backup/";
+$backup_file = date("Ymdhis")."-ISPConfig-letsencrypt.tar.gz";
+$backup_file2 = date("Ymdhis")."-cronjob.txt";
+
+if(!file_exists("/usr/local/ispconfig/server/lib/config.inc.php") OR !file_exists("/usr/local/ispconfig/server/lib/mysql_clientdb.conf")) {
+ echo "ERROR: Unable to load the ISPConfig defaut configuration files.\n";
+ exit;
+}
+
+require_once "/usr/local/ispconfig/server/lib/config.inc.php";
+require_once "/usr/local/ispconfig/server/lib/mysql_clientdb.conf";
+
+if($conf["app_version"] != "3.0.5.4p8") {
+ echo "ERROR: This version is unsupported.\n";
+ exit;
+}
+
+if(!file_exists($backup_dir)) {
+ echo "Backup directory not found.\n";
+ mkdir($backup_dir, 0700);
+}
+
+if(!file_exists($backup_dir)) {
+ echo "ERROR: Create it, and relaunch me!\n";
+ exit;
+}
+
+if(getcwd() != realpath(dirname(__FILE__))) {
+ echo "ERROR: Run me in current installer directory!\n";
+ exit;
+}
+
+echo "Create backup on " . $backup_dir . " directory\n";
+
+exec("/bin/tar -czf " . $backup_dir . $backup_file . " /usr/local/ispconfig");
+
+if(!file_exists($backup_dir . $backup_file )) {
+ echo "ERROR: There was a problem with the backup file.\n";
+ exit;
+}
+
+echo "Backup finished\n";
+
+if(!is_dir("/etc/letsencrypt")) {
+ echo "ERROR: Let's Encrypt directory ( /etc/letsencrypt/ ) is missing, install it corecctly!\n";
+ exit;
+}
+
+if(!is_file("/root/.local/share/letsencrypt/bin/letsencrypt")) {
+ echo "ERROR: Let's Encrypt ( /root/.local/share/letsencrypt/bin/letsencrypt ) is missing, install it corecctly!\n";
+ exit;
+}
+
+if(!is_file("/root/.local/share/letsencrypt/bin/letsencrypt-renewer")) {
+ echo "ERROR: Let's Encrypt ( /root/.local/share/letsencrypt/bin/letsencrypt-renewer ) is missing, install it corecctly!\n";
+ exit;
+}
+
+if(!is_file("/etc/letsencrypt/cli.ini")) {
+ echo "Let's Encrypt configuration file don't exist, create it.\n";
+ exec("cp ./cli.ini /etc/letsencrypt/cli.ini");
+} else {
+ echo "Let's Encrypt configuration file exist, patch it.\n";
+ exec("patch /etc/letsencrypt/cli.ini < ./cli.ini.patch");
+}
+
+if(!$buffer = mysql_connect($clientdb_host, $clientdb_user, $clientdb_password)) {
+ echo "ERROR: There was a problem with the MySQL connection.\n";
+ exit;
+}
+
+echo "Start MySQL update..\n";
+mysql_db_query($conf['db_database'], "ALTER TABLE `web_domain` ADD `ssl_letsencrypt` enum('n','y') NOT NULL DEFAULT 'n';", $buffer);
+
+if(is_file("/etc/apache2/apache2.conf")) {
+ echo "Configure Apache and reload it.\n";
+ if(is_file("/etc/apache2/conf-available/letsencrypt.conf")) {
+ exec("rm /etc/apache2/conf-available/letsencrypt.conf");
+ }
+ exec("cp ./apache.letsencrypt.conf /etc/apache2/conf-available/letsencrypt.conf");
+ exec("a2enmod headers");
+ exec("a2enconf letsencrypt");
+ exec("service apache2 reload");
+}
+
+if(is_file("/etc/nginx/nginx.conf")) {
+ echo "Patch Nginx and reload it.\n";
+ exec("patch /etc/nginx/nginx.conf < ./nginx.conf.patch");
+ exec("service nginx reload");
+}
+
+echo "Create backup cronjob on " . $backup_dir . " directory\n";
+exec("crontab -l >> " . $backup_dir . $backup_file2);
+if(!file_exists($backup_dir . $backup_file2 )) {
+ echo "ERROR: There was a problem with the cronjob backup file.\n";
+ exit;
+}
+
+exec("crontab -l", $output);
+
+if(!in_array("30 02 * * * /root/.local/share/letsencrypt/bin/letsencrypt-renewer >> /var/log/ispconfig/cron.log; done", $output)) {
+ echo "Add a cronjob for renewal certs\n";
+
+ $output[] = "30 02 * * * /root/.local/share/letsencrypt/bin/letsencrypt-renewer >> /var/log/ispconfig/cron.log; done";
+
+ exec("touch ./crontab.tmp");
+ if(!is_file("./crontab.tmp")) {
+ echo "ERROR: Unable to create temporary crontab file.\n";
+ exit;
+ }
+
+ foreach($output as $line) {
+ exec("echo '" . $line . "' >> ./crontab.tmp");
+ }
+
+ exec("cat ./crontab.tmp", $crontab);
+
+ if(empty(array_diff($output, $crontab))) {
+ exec("crontab ./crontab.tmp");
+ exec("rm ./crontab.tmp");
+ } else {
+ echo "ERROR: There was a problem with the cronjob temporary file.\n";
+ exit;
+ }
+} else {
+ echo "Renewer already present in crontab.\n";
+}
+
+echo "And finally, patch ISPConfig.\n";
+exec("cp ispconfig.patch /usr/local/ispconfig/ispconfig.patch");
+exec("cd /usr/local/ispconfig");
+exec("patch -p3 < ./ispconfig.patch");
+exec("rm ./ispconfig.patch");
+
+echo "Done my job. Enjoy!\n";
+exit;
+?>
diff --git a/ispconfig.patch b/ispconfig.patch
new file mode 100644
index 0000000..72073f8
--- /dev/null
+++ b/ispconfig.patch
@@ -0,0 +1,466 @@
+diff -u -r /root/ispconfig/interface/web/sites/form/web_domain.tform.php /usr/local/ispconfig/interface/web/sites/form/web_domain.tform.php
+--- /root/ispconfig/interface/web/sites/form/web_domain.tform.php 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/form/web_domain.tform.php 2015-11-05 02:28:13.272000000 +0100
+@@ -232,6 +232,12 @@
+ 'default' => 'n',
+ 'value' => array(0 => 'n', 1 => 'y')
+ ),
++ 'ssl_letsencrypt' => array (
++ 'datatype' => 'VARCHAR',
++ 'formtype' => 'CHECKBOX',
++ 'default' => 'n',
++ 'value' => array(0 => 'n', 1 => 'y')
++ ),
+ 'php' => array (
+ 'datatype' => 'VARCHAR',
+ 'formtype' => 'SELECT',
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/ar_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/ar_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/ar_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/ar_web_domain.lng 2015-11-06 18:36:40.896000000 +0100
+@@ -28,6 +28,7 @@
+ $wb['errordocs_txt'] = 'Own Error-Documents';
+ $wb['subdomain_txt'] = 'Auto-Subdomain';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'Client';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/bg_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/bg_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/bg_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/bg_web_domain.lng 2015-11-06 18:36:41.096000000 +0100
+@@ -26,6 +26,7 @@
+ $wb['ssi_txt'] = 'SSI';
+ $wb['errordocs_txt'] = 'Собствени страници за грешки';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'Клиент';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/br_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/br_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/br_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/br_web_domain.lng 2015-11-06 18:36:40.896000000 +0100
+@@ -27,6 +27,7 @@
+ $wb['errordocs_txt'] = 'Suas Páginas de Erro';
+ $wb['subdomain_txt'] = 'Auto-Subdomínio';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'Cliente';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/cz_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/cz_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/cz_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/cz_web_domain.lng 2015-11-06 18:36:40.920000000 +0100
+@@ -27,6 +27,7 @@
+ $wb['ssi_txt'] = 'SSI';
+ $wb['subdomain_txt'] = 'Automatická subdoména';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'Klient';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/de_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/de_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/de_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/de_web_domain.lng 2015-11-06 18:36:38.772000000 +0100
+@@ -27,6 +27,7 @@
+ $wb['cgi_txt'] = 'CGI';
+ $wb['ssi_txt'] = 'SSI';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'Kunde';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/el_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/el_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/el_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/el_web_domain.lng 2015-11-06 18:36:39.484000000 +0100
+@@ -30,6 +30,7 @@
+ $wb['errordocs_txt'] = 'Προσωπικά έγγραφα σφάλματος';
+ $wb['subdomain_txt'] = 'Auto-Subdomain';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'Πελάτης';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/en_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/en_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/en_web_domain.lng 2015-11-07 13:37:31.740000000 +0100
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/en_web_domain.lng 2015-11-07 13:37:36.004000000 +0100
+@@ -33,6 +33,7 @@
+ $wb["errordocs_txt"] = 'Own Error-Documents';
+ $wb["subdomain_txt"] = 'Auto-Subdomain';
+ $wb["ssl_txt"] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb["suexec_txt"] = 'SuEXEC';
+ $wb["php_txt"] = 'PHP';
+ $wb["client_txt"] = 'Client';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/es_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/es_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/es_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/es_web_domain.lng 2015-11-06 18:36:38.360000000 +0100
+@@ -31,6 +31,7 @@
+ $wb['errordocs_txt'] = 'Documentos propios de error';
+ $wb['subdomain_txt'] = 'Auto-Subdominio';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'Cliente';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/fi_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/fi_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/fi_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/fi_web_domain.lng 2015-11-06 18:36:38.376000000 +0100
+@@ -25,6 +25,7 @@
+ $wb['cgi_txt'] = 'CGI';
+ $wb['ssi_txt'] = 'SSI';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'Asiakas';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/fr_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/fr_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/fr_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/fr_web_domain.lng 2015-11-06 18:36:41.744000000 +0100
+@@ -25,6 +25,7 @@
+ $wb['ssi_txt'] = 'SSI';
+ $wb['errordocs_txt'] = 'Pages derreurs personnalisées';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'Client';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/hr_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/hr_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/hr_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/hr_web_domain.lng 2015-11-06 18:36:38.412000000 +0100
+@@ -30,6 +30,7 @@
+ $wb['errordocs_txt'] = 'Vlastite error stranice';
+ $wb['subdomain_txt'] = 'Automatska poddomena';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'Klijent';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/hu_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/hu_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/hu_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/hu_web_domain.lng 2015-11-06 18:36:35.844000000 +0100
+@@ -26,6 +26,7 @@
+ $wb['ssi_txt'] = 'SSI';
+ $wb['errordocs_txt'] = 'Saját hibaoldal';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['disabled_txt'] = 'Letiltva';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/id_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/id_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/id_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/id_web_domain.lng 2015-11-06 18:36:36.228000000 +0100
+@@ -28,6 +28,7 @@
+ $wb['errordocs_txt'] = 'Dokumen-Kesalahan Pribadi';
+ $wb['subdomain_txt'] = 'Subdomain Otomatis';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'Klien';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/it_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/it_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/it_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/it_web_domain.lng 2015-11-06 18:36:36.892000000 +0100
+@@ -26,6 +26,7 @@
+ $wb['ssi_txt'] = 'SSI';
+ $wb['errordocs_txt'] = 'Errori personalizzati';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'Cliente';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/ja_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/ja_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/ja_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/ja_web_domain.lng 2015-11-06 18:36:34.476000000 +0100
+@@ -27,6 +27,7 @@
+ $wb['errordocs_txt'] = '独自のエラーページを使う';
+ $wb['subdomain_txt'] = '自動サブドメイン';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'クライアント';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/nl_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/nl_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/nl_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/nl_web_domain.lng 2015-11-06 18:36:35.852000000 +0100
+@@ -30,6 +30,7 @@
+ $wb['errordocs_txt'] = 'Own Error-documenten';
+ $wb['subdomain_txt'] = 'Auto-subdomein';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'Klant';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/pl_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/pl_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/pl_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/pl_web_domain.lng 2015-11-06 18:36:35.828000000 +0100
+@@ -27,6 +27,7 @@
+ $wb['errordocs_txt'] = 'Własne strony błędów';
+ $wb['subdomain_txt'] = 'Automatyczna subdomena';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'Klient';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/pt_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/pt_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/pt_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/pt_web_domain.lng 2015-11-06 18:36:33.296000000 +0100
+@@ -27,6 +27,7 @@
+ $wb['errordocs_txt'] = 'Páginas de Erro';
+ $wb['subdomain_txt'] = 'Auto-Subdomínio';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'Cliente';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/ro_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/ro_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/ro_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/ro_web_domain.lng 2015-11-06 18:36:33.884000000 +0100
+@@ -27,6 +27,7 @@
+ $wb['errordocs_txt'] = 'Own Error-Documents';
+ $wb['subdomain_txt'] = 'Auto-Subdomain';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'Client';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/ru_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/ru_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/ru_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/ru_web_domain.lng 2015-11-06 18:36:54.424000000 +0100
+@@ -25,6 +25,7 @@
+ $wb['cgi_txt'] = 'CGI';
+ $wb['ssi_txt'] = 'SSI';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'Клиент';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/se_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/se_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/se_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/se_web_domain.lng 2015-11-06 18:36:33.256000000 +0100
+@@ -26,6 +26,7 @@
+ $wb['ssi_txt'] = 'SSI';
+ $wb['errordocs_txt'] = 'Own Error-Documents';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'Client';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/sk_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/sk_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/sk_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/sk_web_domain.lng 2015-11-06 18:36:33.096000000 +0100
+@@ -27,6 +27,7 @@
+ $wb['errordocs_txt'] = 'Vlastné Error-Dokumenty';
+ $wb['subdomain_txt'] = 'Auto-Subdomény';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'Klient';
+diff -u -r /root/ispconfig/interface/web/sites/lib/lang/tr_web_domain.lng /usr/local/ispconfig/interface/web/sites/lib/lang/tr_web_domain.lng
+--- /root/ispconfig/interface/web/sites/lib/lang/tr_web_domain.lng 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/interface/web/sites/lib/lang/tr_web_domain.lng 2015-11-06 18:39:23.560000000 +0100
+@@ -27,6 +27,7 @@
+ $wb['errordocs_txt'] = 'Özelleştirilebilir Hata Sayfaları';
+ $wb['subdomain_txt'] = 'Otomatik Subdomain';
+ $wb['ssl_txt'] = 'SSL';
++$wb['ssl_letsencrypt_txt'] = 'Let\'s Encrypt';
+ $wb['suexec_txt'] = 'SuEXEC';
+ $wb['php_txt'] = 'PHP';
+ $wb['client_txt'] = 'Müşteri';
+diff -u -r /root/ispconfig/interface/web/sites/templates/web_domain_edit.htm /usr/local/ispconfig/interface/web/sites/templates/web_domain_edit.htm
+--- /root/ispconfig/interface/web/sites/templates/web_domain_edit.htm 2015-11-06 20:44:44.560000000 +0100
++++ /usr/local/ispconfig/interface/web/sites/templates/web_domain_edit.htm 2015-11-06 20:44:05.192000000 +0100
+@@ -130,6 +130,12 @@
+ <div class="multiField">
+ {tmpl_var name='ssl'}
+ </div>
++ </div>
++ <div class="ctrlHolder">
++ <p class="label">{tmpl_var name='ssl_letsencrypt_txt'}</p>
++ <div class="multiField">
++ {tmpl_var name='ssl_letsencrypt'}
++ </div>
+ </div></tmpl_if>
+ <div class="ctrlHolder">
+ <label for="php">{tmpl_var name='php_txt'}</label>
+@@ -261,5 +267,11 @@
+ submitForm('pageForm','sites/web_domain_edit.php');
+ });
+ </tmpl_if>
+-
+-</script>
+\ No newline at end of file
++
++ jQuery('input#ssl_letsencrypt').bind('change', function() {
++ if(jQuery('input#ssl_letsencrypt').is(":checked")) jQuery('input#ssl').prop('checked', true);
++ });
++ jQuery('input#ssl').bind('change', function() {
++ if(jQuery('input#ssl_letsencrypt').is(":checked")) jQuery('input#ssl_letsencrypt').prop('checked', false);
++ });
++</script>
+diff -u -r /root/ispconfig/server/conf/nginx_vhost.conf.master /usr/local/ispconfig/server/conf/nginx_vhost.conf.master
+--- /root/ispconfig/server/conf/nginx_vhost.conf.master 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/server/conf/nginx_vhost.conf.master 2015-11-08 02:40:25.192000000 +0100
+@@ -105,12 +105,14 @@
+ access_log /var/log/ispconfig/httpd/<tmpl_var name='domain'>/access.log combined;
+
+ ## Disable .htaccess and other hidden files
++<tmpl_if name='ssl_letsencrypt' op='!=' value='y'>
+ location ~ /\. {
+ deny all;
+ access_log off;
+ log_not_found off;
+ }
+-
++</tmpl_if>
++
+ location = /favicon.ico {
+ log_not_found off;
+ access_log off;
+@@ -229,4 +231,4 @@
+ }
+ </tmpl_if>
+ }
+-</tmpl_loop>
+\ No newline at end of file
++</tmpl_loop>
+diff -u -r /root/ispconfig/server/plugins-available/apache2_plugin.inc.php /usr/local/ispconfig/server/plugins-available/apache2_plugin.inc.php
+--- /root/ispconfig/server/plugins-available/apache2_plugin.inc.php 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/server/plugins-available/apache2_plugin.inc.php 2015-11-08 03:03:12.028000000 +0100
+@@ -935,7 +935,7 @@
+
+ // Check if a SSL cert exists
+ $ssl_dir = $data['new']['document_root'].'/ssl';
+- $domain = $data['new']['ssl_domain'];
++ $domain = $data['new']['domain'];
+ $key_file = $ssl_dir.'/'.$domain.'.key';
+ $crt_file = $ssl_dir.'/'.$domain.'.crt';
+ $bundle_file = $ssl_dir.'/'.$domain.'.bundle';
+@@ -950,6 +950,57 @@
+ }
+ */
+
++ //* Generate Let's Encrypt SSL certificat
++ if($data['new']['ssl'] == 'y' && $data['new']['ssl_letsencrypt'] == 'y') {
++//* TODO: check dns entry is correct
++ $crt_tmp_file = "/etc/letsencrypt/live/".$domain."/cert.pem";
++ $key_tmp_file = "/etc/letsencrypt/live/".$domain."/privkey.pem";
++ $webroot = $data['new']['document_root']."/web";
++
++ //* check if we have already a Let's Encrypt cert
++ if(!file_exists($crt_tmp_file) && !file_exists($key_tmp_file)) {
++ exec("/root/.local/share/letsencrypt/bin/letsencrypt auth -a webroot --email postmaster@$domain --domains $domain --webroot-path $webroot --text --agree-tos");
++ $app->log("Creating Let's Encrypt SSL Cert for: $domain", LOGLEVEL_DEBUG);
++ };
++
++ //* check is been correctly created
++ if(file_exists($crt_tmp_file) OR file_exists($key_tmp_file)) {
++ $date = date("YmdHis");
++//* TODO: check if is a symlink, if target same keep it, either remove it
++ if(is_file($key_file)) {
++ $app->system->copy($key_file, $key_file.'.old'.$date);
++ $app->system->chmod($key_file.'.old.'.$date, 0400);
++ $app->system->unlink($key_file);
++ }
++
++ if ($web_config["website_symlinks_rel"] == 'y') {
++ $this->create_relative_link(escapeshellcmd($key_tmp_file), escapeshellcmd($key_file));
++ } else {
++ exec("ln -s ".escapeshellcmd($key_tmp_file)." ".escapeshellcmd($key_file));
++ }
++
++ if(is_file($crt_file)) {
++ $app->system->copy($crt_file, $crt_file.'.old.'.$date);
++ $app->system->chmod($crt_file.'.old.'.$date, 0400);
++ $app->system->unlink($crt_file);
++ }
++
++ if($web_config["website_symlinks_rel"] == 'y') {
++ $this->create_relative_link(escapeshellcmd($crt_tmp_file), escapeshellcmd($crt_file));
++ } else {
++ exec("ln -s ".escapeshellcmd($crt_tmp_file)." ".escapeshellcmd($crt_file));
++ }
++
++ /* we don't need to store it.
++ /* Update the DB of the (local) Server */
++ $app->db->query("UPDATE web_domain SET ssl_request = '', ssl_cert = '$ssl_cert', ssl_key = '$ssl_key' WHERE domain = '".$data['new']['domain']."'");
++ $app->db->query("UPDATE web_domain SET ssl_action = '' WHERE domain = '".$data['new']['domain']."'");
++ /* Update also the master-DB of the Server-Farm */
++ $app->dbmaster->query("UPDATE web_domain SET ssl_request = '', ssl_cert = '$ssl_cert', ssl_key = '$ssl_key' WHERE domain = '".$data['new']['domain']."'");
++ $app->dbmaster->query("UPDATE web_domain SET ssl_action = '' WHERE domain = '".$data['new']['domain']."'");
++ }
++ };
++
+ if(@is_file($bundle_file)) $vhost_data['has_bundle_cert'] = 1;
+
+ //$vhost_data['document_root'] = $data['new']['document_root'].'/' . $web_folder;
+diff -u -r /root/ispconfig/server/plugins-available/nginx_plugin.inc.php /usr/local/ispconfig/server/plugins-available/nginx_plugin.inc.php
+--- /root/ispconfig/server/plugins-available/nginx_plugin.inc.php 2015-06-05 10:06:30.000000000 +0200
++++ /usr/local/ispconfig/server/plugins-available/nginx_plugin.inc.php 2015-11-08 03:13:36.524000000 +0100
+@@ -1102,10 +1102,66 @@
+
+ // Check if a SSL cert exists
+ $ssl_dir = $data['new']['document_root'].'/ssl';
++ if(!isset($data['new']['ssl_domain']) OR empty($data['new']['ssl_domain'])) { $data['new']['ssl_domain'] = $data['new']['domain']; }
+ $domain = $data['new']['ssl_domain'];
++ $tpl->setVar('ssl_domain', $domain);
+ $key_file = $ssl_dir.'/'.$domain.'.key';
+ $crt_file = $ssl_dir.'/'.$domain.'.crt';
+
++
++ $tpl->setVar('ssl_letsencrypt', "n");
++ //* Generate Let's Encrypt SSL certificat
++ if($data['new']['ssl'] == 'y' && $data['new']['ssl_letsencrypt'] == 'y') {
++ $tpl->setVar('ssl_letsencrypt', "y");
++ //* TODO: check dns entry is correct
++ $crt_tmp_file = "/etc/letsencrypt/live/".$domain."/fullchain.pem";
++ $key_tmp_file = "/etc/letsencrypt/live/".$domain."/privkey.pem";
++ $webroot = $data['new']['document_root']."/web";
++
++ //* check if we have already a Let's Encrypt cert
++ if(!file_exists($crt_tmp_file) && !file_exists($key_tmp_file)) {
++ exec("/root/.local/share/letsencrypt/bin/letsencrypt auth -a webroot --email postmaster@$domain --domains $domain --webroot-path $webroot --text --agree-tos");
++ $app->log("Creating Let's Encrypt SSL Cert for: $domain", LOGLEVEL_DEBUG);
++ };
++
++ //* check is been correctly created
++ if(file_exists($crt_tmp_file) OR file_exists($key_tmp_file)) {
++ $date = date("YmdHis");
++//* TODO: check if is a symlink, if target same keep it, either remove it
++ if(is_file($key_file)) {
++ $app->system->copy($key_file, $key_file.'.old'.$date);
++ $app->system->chmod($key_file.'.old.'.$date, 0400);
++ $app->system->unlink($key_file);
++ }
++
++ if ($web_config["website_symlinks_rel"] == 'y') {
++ $this->create_relative_link(escapeshellcmd($key_tmp_file), escapeshellcmd($key_file));
++ } else {
++ exec("ln -s ".escapeshellcmd($key_tmp_file)." ".escapeshellcmd($key_file));
++ }
++
++ if(is_file($crt_file)) {
++ $app->system->copy($crt_file, $crt_file.'.old.'.$date);
++ $app->system->chmod($crt_file.'.old.'.$date, 0400);
++ $app->system->unlink($crt_file);
++ }
++
++ if($web_config["website_symlinks_rel"] == 'y') {
++ $this->create_relative_link(escapeshellcmd($crt_tmp_file), escapeshellcmd($crt_file));
++ } else {
++ exec("ln -s ".escapeshellcmd($crt_tmp_file)." ".escapeshellcmd($crt_file));
++ }
++
++ /* we don't need to store it.
++ /* Update the DB of the (local) Server */
++ $app->db->query("UPDATE web_domain SET ssl_request = '', ssl_cert = '', ssl_key = '' WHERE domain = '".$data['new']['domain']."'");
++ $app->db->query("UPDATE web_domain SET ssl_action = '' WHERE domain = '".$data['new']['domain']."'");
++ /* Update also the master-DB of the Server-Farm */
++ $app->dbmaster->query("UPDATE web_domain SET ssl_request = '', ssl_cert = '', ssl_key = '' WHERE domain = '".$data['new']['domain']."'");
++ $app->dbmaster->query("UPDATE web_domain SET ssl_action = '' WHERE domain = '".$data['new']['domain']."'");
++ }
++ };
++
+ if($domain!='' && $data['new']['ssl'] == 'y' && @is_file($crt_file) && @is_file($key_file) && (@filesize($crt_file)>0) && (@filesize($key_file)>0)) {
+ $vhost_data['ssl_enabled'] = 1;
+ $app->log('Enable SSL for: '.$domain, LOGLEVEL_DEBUG); \ No newline at end of file
diff --git a/nginx.conf.patch b/nginx.conf.patch
new file mode 100644
index 0000000..b49364b
--- /dev/null
+++ b/nginx.conf.patch
@@ -0,0 +1,15 @@
+--- /etc/nginx/nginx.conf.orig 2015-11-08 01:44:42.558552834 +0100
++++ /etc/nginx/nginx.conf 2015-11-08 02:10:51.275908452 +0100
+@@ -9,6 +9,12 @@
+
+ http {
+
++ server {
++ location ~ /.well-known/acme-challenge/(.*) {
++ default_type application/jose+json;
++ }
++ }
++
+ ##
+ # Basic Settings
+ ##