1
0
Fork 0
mirror of synced 2024-05-20 12:42:39 +12:00

Added master domain SSL cert

This commit is contained in:
Eldad Fux 2020-03-01 08:33:19 +02:00
parent 0082e28e8e
commit eef5125077
11 changed files with 111 additions and 38 deletions

View file

@ -46,12 +46,13 @@ ENV TZ=Asia/Tel_Aviv \
DEBIAN_FRONTEND=noninteractive \
PHP_VERSION=7.4 \
_APP_ENV=production \
_APP_DOMAIN=localhost \
_APP_DOMAIN_TARGET=localhost \
_APP_HOME=https://appwrite.io \
_APP_EDITION=community \
_APP_OPTIONS_ABUSE=enabled \
_APP_OPENSSL_KEY_V1=your-secret-key \
_APP_STORAGE_LIMIT=104857600 \
_APP_DOMAINS_TARGET=localhost \
_APP_REDIS_HOST=redis \
_APP_REDIS_PORT=6379 \
_APP_DB_HOST=mariadb \
@ -100,8 +101,12 @@ RUN \
rm -rf /var/lib/apt/lists/*
# Set Upload Limit (default to 100MB)
RUN echo "upload_max_filesize = ${_APP_STORAGE_LIMIT}" > /etc/php/$PHP_VERSION/fpm/conf.d/appwrite.ini
RUN echo "post_max_size = ${_APP_STORAGE_LIMIT}" > /etc/php/$PHP_VERSION/fpm/conf.d/appwrite.ini
RUN echo "upload_max_filesize = ${_APP_STORAGE_LIMIT}" >> /etc/php/$PHP_VERSION/fpm/conf.d/appwrite.ini
RUN echo "post_max_size = ${_APP_STORAGE_LIMIT}" >> /etc/php/$PHP_VERSION/fpm/conf.d/appwrite.ini
RUN echo "env[TESTME] = your-secret-key" >> /etc/php/$PHP_VERSION/fpm/conf.d/appwrite.ini
# Add logs file
RUN echo "" >> /var/log/appwrite.log
# Nginx Configuration (with self-signed ssl certificates)
COPY ./docker/nginx.conf /etc/nginx/nginx.conf

View file

@ -1214,7 +1214,7 @@ $utopia->post('/v1/projects/:projectId/domains')
throw new Exception('Domain already exists', 409);
}
$target = new Domain($request->getServer('_APP_DOMAINS_TARGET', ''));
$target = new Domain($request->getServer('_APP_DOMAIN_TARGET', ''));
if(!$target->isKnown() || $target->isTest()) {
throw new Exception('Unreachable CNAME target ('.$target->get().'), plesse use a domain with a public suffix.', 500);
@ -1321,7 +1321,7 @@ $utopia->patch('/v1/projects/:projectId/domains/:domainId/verification')
throw new Exception('Domain not found', 404);
}
$target = new Domain($request->getServer('_APP_DOMAINS_TARGET', ''));
$target = new Domain($request->getServer('_APP_DOMAIN_TARGET', ''));
if(!$target->isKnown() || $target->isTest()) {
throw new Exception('Unreachable CNAME target ('.$target->get().'), plesse use a domain with a public suffix.', 500);

View file

@ -118,7 +118,7 @@ $utopia->get('/console/settings')
->label('permission', 'public')
->label('scope', 'console')
->action(function () use ($request, $layout) {
$target = new Domain($request->getServer('_APP_DOMAINS_TARGET', ''));
$target = new Domain($request->getServer('_APP_DOMAIN_TARGET', ''));
$page = new View(__DIR__.'/../../views/console/settings/index.phtml');

29
app/tasks/init.php Normal file
View file

@ -0,0 +1,29 @@
#!/bin/env php
<?php
require_once __DIR__.'/../init.php';
global $request;
use Utopia\CLI\CLI;
use Utopia\CLI\Console;
$cli = new CLI();
$cli
->task('ssl')
->desc('Validate server certificates')
->action(function () use ($request) {
$domain = $request->getServer('_APP_DOMAIN', '');
Console::log('Issue a TLS certificate for master domain ('.$domain.')');
Resque::enqueue('v1-certificates', 'CertificatesV1', [
'document' => [],
'domain' => $domain,
'validateTarget' => false,
'validateCNAME' => false,
]);
});
$cli->run();

View file

@ -160,7 +160,7 @@ $customDomainsTarget = $this->getParam('customDomainsTarget', false);
<p>To enable <?php echo APP_NAME; ?>'s custom domain feature, you have to start your server instance with a public accessable domain name.</p>
<p>Start your <?php echo APP_NAME; ?> server container with the <b>_APP_DOMAINS_TARGET</b> enviornment variable set with a public accessable domain name that resolves to your <?php echo APP_NAME; ?> server setup.</p>
<p>Start your <?php echo APP_NAME; ?> server container with the <b>_APP_DOMAIN_TARGET</b> enviornment variable set with a public accessable domain name that resolves to your <?php echo APP_NAME; ?> server setup.</p>
<p class="margin-bottom-no">The <?php echo APP_NAME; ?> server will use your target domain to validate new custom domains and will automatically generate SSL certificates for your new domains using letsencrypt certbot.</p>
</div>
<?php endif; ?>
@ -201,7 +201,7 @@ $customDomainsTarget = $this->getParam('customDomainsTarget', false);
<span class="text-size-small text-info" data-ls-if="true === {{domain.verification}}"><i class="icon-ok-circled"></i> Verified&nbsp;</span>
</td>
<td data-title="Domain: ">
<span data-ls-bind="{{domain.domain}}"></span>
<span class="text-size-small" data-ls-bind="{{domain.domain}}"></span>
</td>
<td data-title="TLS: ">
<span class="text-size-small text-fade" data-ls-if="!{{domain.certificateId}} && false === {{domain.verification}}"> &nbsp;Pending Verification&nbsp;</span>

View file

@ -96,9 +96,9 @@ $providers = $this->getParam('providers', []);
<tr>
<th width="60"></th>
<th width="180">Name</th>
<th width="220">Email</th>
<th>Status</th>
<th width="100">Joined</th>
<th>Email</th>
<th width="120">Status</th>
<th width="120">Joined</th>
</tr>
</thead>
<tbody data-ls-loop="project-users.users" data-ls-as="user">
@ -117,15 +117,15 @@ $providers = $this->getParam('providers', []);
</td>
<td data-title="Status: ">
<span data-ls-if="{{user.emailVerification}} === true">
&nbsp;<span class="tag green">Verified</span>
<span class="tag green">Verified</span>
</span>
<span data-ls-if="{{user.emailVerification}} !== true">
&nbsp;<span class="tag">Unverified</span>
<span class="tag">Unverified</span>
</span>
<span data-ls-if="{{user.status}} === <?php echo \Auth\Auth::USER_STATUS_BLOCKED; ?>">
&nbsp;<span class="tag red">Blocked</span>
<span class="tag red">Blocked</span>
</span>
</td>
<td data-title="Created: "><small data-ls-bind="{{user.registration|date-text}}"></small></td>
@ -242,8 +242,8 @@ $providers = $this->getParam('providers', []);
<thead>
<tr>
<th width="60"></th>
<th width="180">Name</th>
<th>Members</th>
<th>Name</th>
<th width="150">Members</th>
<th width="150">Created</th>
</tr>
</thead>

View file

@ -38,31 +38,46 @@ class CertificatesV1
Authorization::disable();
$document = $this->args['document'];
$domain = $this->args['domain'];
$domain = new Domain((!empty($domain)) ? $domain : '');
$expiry = 60 * 60 * 24 * 30 * 2; // 60 days
$safety = 60 * 60; // 1 hour
$renew = (time() + $expiry);
// Args
$document = $this->args['document'];
$domain = $this->args['domain'];
// Validation Args
$validateTarget = (isset($this->args['validateTarget'])) ? $this->args['validateTarget'] : true;
$validateCNAME = (isset($this->args['validateCNAME'])) ? $this->args['validateCNAME'] : true;
// Options
$domain = new Domain((!empty($domain)) ? $domain : '');
$expiry = 60 * 60 * 24 * 30 * 2; // 60 days
$safety = 60 * 60; // 1 hour
$renew = (time() + $expiry);
if(empty($domain->get())) {
echo 'Log: Missing domain';
throw new Exception('Missing domain');
}
if(!$domain->isKnown() || $domain->isTest()) {
echo 'Log: Unkown public suffix for domain';
throw new Exception('Unkown public suffix for domain');
}
$target = new Domain($request->getServer('_APP_DOMAINS_TARGET', ''));
if(!$target->isKnown() || $target->isTest()) {
throw new Exception('Unreachable CNAME target ('.$target->get().'), plesse use a domain with a public suffix.', 500);
if($validateTarget) {
$target = new Domain($request->getServer('_APP_DOMAIN_TARGET', ''));
if(!$target->isKnown() || $target->isTest()) {
echo 'Log: Unreachable CNAME target ('.$target->get().'), plesse use a domain with a public suffix.';
throw new Exception('Unreachable CNAME target ('.$target->get().'), plesse use a domain with a public suffix.');
}
}
$validator = new CNAME($target->get()); // Verify Domain with DNS records
if(!$validator->isValid($domain->get())) {
throw new Exception('Failed to verify domain DNS records');
if($validateCNAME) {
$validator = new CNAME($target->get()); // Verify Domain with DNS records
if(!$validator->isValid($domain->get())) {
echo 'Log: Failed to verify domain DNS records';
throw new Exception('Failed to verify domain DNS records');
}
}
$certificate = $consoleDB->getCollection([
@ -84,6 +99,7 @@ class CertificatesV1
&& $certificate instanceof Document
&& isset($certificate['issueDate'])
&& (($certificate['issueDate'] + ($expiry)) > time())) { // Check last issue time
echo 'Log: Renew isn\'t required. Domain issued at '.date('d.m.Y H:i', (isset($certificate['issueDate']) ? $certificate['issueDate'] : 0));
throw new Exception('Renew isn\'t required. Domain issued at '.date('d.m.Y H:i', (isset($certificate['issueDate']) ? $certificate['issueDate'] : 0)));
}
@ -94,6 +110,7 @@ class CertificatesV1
-d {$domain->get()} 2>&1");
if(!$response) {
echo 'Log: Failed to issue a certificate';
throw new Exception('Failed to issue a certificate');
}
@ -101,23 +118,28 @@ class CertificatesV1
if(!is_readable($path)) {
if (!mkdir($path, 0755, true)) {
echo 'Log: Failed to create path...';
throw new Exception('Failed to create path...');
}
}
if(!@rename('/etc/letsencrypt/live/'.$domain->get().'/cert.pem', APP_STORAGE_CERTIFICATES.'/'.$domain->get().'/cert.pem')) {
echo 'Log: Failed to create path... 1';
throw new Exception('Failed to rename certificate cert.pem: '.json_encode($response));
}
if(!@rename('/etc/letsencrypt/live/'.$domain->get().'/chain.pem', APP_STORAGE_CERTIFICATES.'/'.$domain->get().'/chain.pem')) {
echo 'Log: Failed to create path... 2';
throw new Exception('Failed to rename certificate chain.pem: '.json_encode($response));
}
if(!@rename('/etc/letsencrypt/live/'.$domain->get().'/fullchain.pem', APP_STORAGE_CERTIFICATES.'/'.$domain->get().'/fullchain.pem')) {
echo 'Log: Failed to create path... 3';
throw new Exception('Failed to rename certificate fullchain.pem: '.json_encode($response));
}
if(!@rename('/etc/letsencrypt/live/'.$domain->get().'/privkey.pem', APP_STORAGE_CERTIFICATES.'/'.$domain->get().'/privkey.pem')) {
echo 'Log: Failed to create path... 4';
throw new Exception('Failed to rename certificate privkey.pem: '.json_encode($response));
}
@ -137,6 +159,7 @@ class CertificatesV1
$certificate = $consoleDB->createDocument($certificate);
if(!$certificate) {
echo 'Log: Failed saving certificate to DB';
throw new Exception('Failed saving certificate to DB');
}
@ -149,6 +172,7 @@ class CertificatesV1
$document = $consoleDB->updateDocument($document);
if(!$document) {
echo 'Log: Failed saving domain to DB';
throw new Exception('Failed saving domain to DB');
}
}
@ -160,6 +184,7 @@ class CertificatesV1
keyFile: /storage/certificates/{$domain->get()}/privkey.pem";
if(!file_put_contents(APP_STORAGE_CONFIG.'/'.$domain->get().'.yml', $config)) {
echo 'Log: Failed to save SSL configuration';
throw new Exception('Failed to save SSL configuration');
}

View file

@ -66,7 +66,8 @@ services:
# - _APP_ENV=development
- _APP_OPTIONS_ABUSE=disabled
- _APP_OPENSSL_KEY_V1=your-secret-key
- _APP_DOMAINS_TARGET=demo.appwrite.io
- _APP_DOMAIN=demo.appwrite.io
- _APP_DOMAIN_TARGET=demo.appwrite.io
- _APP_REDIS_HOST=redis
- _APP_REDIS_PORT=6379
- _APP_DB_HOST=mariadb

View file

@ -12,13 +12,13 @@ function setEnvironmentVariable() {
fi
# Check whether variable already exists
if grep -q $1 /etc/php/$PHP_VERSION/fpm/pool.d/www.conf; then
# Reset variable
sed -i "s/^env\[$1.*/env[$1] = $2/g" /etc/php/$PHP_VERSION/fpm/pool.d/www.conf
else
if ! grep -q "\[$1\]" /etc/php/$PHP_VERSION/fpm/pool.d/www.conf; then
# Add variable
echo "env[$1] = $2" >> /etc/php/$PHP_VERSION/fpm/pool.d/www.conf
fi
# Reset variable
# sed -i "s/^env\[$1.*/env[$1] = $2/g" /etc/php/$PHP_VERSION/fpm/pool.d/www.conf
}
# Grep for variables that look like MySQL (APP_)
@ -28,5 +28,8 @@ for _curVar in $(env | grep _APP_ | awk -F = '{print $1}');do
setEnvironmentVariable ${_curVar} ${!_curVar}
done
# Init server settings
php /usr/share/nginx/html/app/tasks/init.php ssl
# Start supervisord and services
/usr/bin/supervisord -n -c /etc/supervisord.conf

View file

@ -60,6 +60,8 @@ stopsignal=QUIT
startretries=10
;stdout_logfile=/dev/stdout
;stdout_logfile_maxbytes=0
stdout_logfile=/var/log/appwrite.log
stdout_logfile_maxbytes=5000000
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes = 0
@ -75,6 +77,8 @@ stopsignal=QUIT
startretries=10
;stdout_logfile=/dev/stdout
;stdout_logfile_maxbytes=0
stdout_logfile=/var/log/appwrite.log
stdout_logfile_maxbytes=5000000
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes = 0
@ -90,6 +94,8 @@ stopsignal=QUIT
startretries=10
;stdout_logfile=/dev/stdout
;stdout_logfile_maxbytes=0
stdout_logfile=/var/log/appwrite.log
stdout_logfile_maxbytes=5000000
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes = 0
@ -105,6 +111,8 @@ stopsignal=QUIT
startretries=10
;stdout_logfile=/dev/stdout
;stdout_logfile_maxbytes=0
stdout_logfile=/var/log/appwrite.log
stdout_logfile_maxbytes=5000000
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes = 0
@ -120,6 +128,8 @@ stopsignal=QUIT
startretries=10
;stdout_logfile=/dev/stdout
;stdout_logfile_maxbytes=0
stdout_logfile=/var/log/appwrite.log
stdout_logfile_maxbytes=5000000
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes = 0

View file

@ -8,13 +8,13 @@
* Rick Cook, The Wizardry Compiled
*/
error_reporting(0);
ini_set('display_errors', 0);
// ini_set('display_errors', 1);
// ini_set('display_startup_errors', 1);
// error_reporting(E_ALL);
error_reporting(0);
ini_set('display_errors', 0);
$path = (isset($_GET['q'])) ? explode('/', $_GET['q']) : [];
$domain = (isset($_SERVER['HTTP_HOST'])) ? $_SERVER['HTTP_HOST'] : '';