1
0
Fork 0
mirror of synced 2024-06-23 08:40:58 +12:00

Merge pull request #497 from appwrite/feat-installation-script

Feature: New installation script
This commit is contained in:
Eldad A. Fux 2020-08-08 13:39:40 +03:00 committed by GitHub
commit e2fd3381d0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 1464 additions and 79 deletions

View file

@ -143,8 +143,10 @@ RUN mkdir -p /storage/uploads && \
# Executables
RUN chmod +x /usr/local/bin/doctor && \
chmod +x /usr/local/bin/install && \
chmod +x /usr/local/bin/migrate && \
chmod +x /usr/local/bin/schedule && \
chmod +x /usr/local/bin/ssl && \
chmod +x /usr/local/bin/test && \
chmod +x /usr/local/bin/worker-audits && \
chmod +x /usr/local/bin/worker-certificates && \

View file

@ -50,9 +50,8 @@ The easiest way to start running your Appwrite server is by running our docker-c
```bash
docker run -it --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume "$(pwd)"/appwrite:/install/appwrite:rw \
-e version=0.7.0 \
appwrite/install
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
appwrite/appwrite:0.7.0
```
### Windows
@ -62,9 +61,8 @@ docker run -it --rm \
```cmd
docker run -it --rm ^
--volume //var/run/docker.sock:/var/run/docker.sock ^
--volume "%cd%"/appwrite:/install/appwrite:rw ^
-e version=0.7.0 ^
appwrite/install
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
appwrite/appwrite:0.7.0
```
#### PowerShell
@ -72,9 +70,8 @@ docker run -it --rm ^
```powershell
docker run -it --rm ,
--volume /var/run/docker.sock:/var/run/docker.sock ,
--volume ${pwd}/appwrite:/install/appwrite:rw ,
-e version=0.7.0 ,
appwrite/install
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw ,
appwrite/appwrite:0.7.0
```
Once the Docker installation completes, go to http://localhost to access the Appwrite console from your browser. Please note that on non-linux native hosts, the server might take a few minutes to start after installation completes.

25
app/cli.php Normal file
View file

@ -0,0 +1,25 @@
#!/bin/env php
<?php
require_once __DIR__.'/init.php';
use Utopia\App;
use Utopia\CLI\CLI;
use Utopia\CLI\Console;
$cli = new CLI();
include 'tasks/doctor.php';
include 'tasks/install.php';
include 'tasks/migrate.php';
include 'tasks/sdks.php';
include 'tasks/ssl.php';
$cli
->task('version')
->desc('Get the server version')
->action(function () {
Console::log(App::getEnv('_APP_VERSION', 'UNKNOWN'));
});
$cli->run();

View file

@ -3,96 +3,96 @@
return [
'/' => [
'name' => 'Homepage',
'controller' => 'controllers/web/home.php',
'controller' => 'web/home.php',
'sdk' => false,
'tests' => false,
],
'console/' => [
'name' => 'Console',
'controller' => 'controllers/web/console.php',
'controller' => 'web/console.php',
'sdk' => false,
'tests' => false,
],
'v1/account' => [
'name' => 'Account',
'description' => '/docs/services/account.md',
'controller' => 'controllers/api/account.php',
'controller' => 'api/account.php',
'sdk' => true,
'tests' => false,
],
'v1/avatars' => [
'name' => 'Avatars',
'description' => '/docs/services/avatars.md',
'controller' => 'controllers/api/avatars.php',
'controller' => 'api/avatars.php',
'sdk' => true,
'tests' => false,
],
'v1/database' => [
'name' => 'Database',
'description' => '/docs/services/database.md',
'controller' => 'controllers/api/database.php',
'controller' => 'api/database.php',
'sdk' => true,
'tests' => false,
],
'v1/locale' => [
'name' => 'Locale',
'description' => '/docs/services/locale.md',
'controller' => 'controllers/api/locale.php',
'controller' => 'api/locale.php',
'sdk' => true,
'tests' => false,
],
'v1/health' => [
'name' => 'Health',
'description' => '/docs/services/health.md',
'controller' => 'controllers/api/health.php',
'controller' => 'api/health.php',
'sdk' => true,
'tests' => false,
],
'v1/projects' => [
'name' => 'Projects',
'controller' => 'controllers/api/projects.php',
'controller' => 'api/projects.php',
'sdk' => true,
'tests' => false,
],
'v1/storage' => [
'name' => 'Storage',
'description' => '/docs/services/storage.md',
'controller' => 'controllers/api/storage.php',
'controller' => 'api/storage.php',
'sdk' => true,
'tests' => false,
],
'v1/teams' => [
'name' => 'Teams',
'description' => '/docs/services/teams.md',
'controller' => 'controllers/api/teams.php',
'controller' => 'api/teams.php',
'sdk' => true,
'tests' => false,
],
'v1/users' => [
'name' => 'Users',
'description' => '/docs/services/users.md',
'controller' => 'controllers/api/users.php',
'controller' => 'api/users.php',
'sdk' => true,
'tests' => false,
],
'v1/functions' => [
'name' => 'Users',
'description' => '/docs/services/functions.md',
'controller' => 'controllers/api/functions.php',
'controller' => 'api/functions.php',
'sdk' => true,
'tests' => false,
],
'v1/mock' => [
'name' => 'Mock',
'description' => '',
'controller' => 'controllers/mock.php',
'controller' => 'mock.php',
'sdk' => false,
'tests' => true,
],
'v1/graphql' => [
'name' => 'GraphQL',
'description' => 'GraphQL Endpoint',
'controller' => 'controllers/api/graphql.php',
'controller' => 'api/graphql.php',
'sdk' => false,
'tests' => false,
],

136
app/config/variables.php Normal file
View file

@ -0,0 +1,136 @@
<?php
return [
[
'name' => '_APP_ENV',
'default' => 'production',
'required' => false,
'question' => '',
],
[
'name' => '_APP_OPTIONS_ABUSE',
'default' => 'enabled',
'required' => false,
'question' => '',
],
[
'name' => '_APP_OPTIONS_FORCE_HTTPS',
'default' => 'enabled',
'required' => false,
'question' => '',
],
[
'name' => '_APP_OPENSSL_KEY_V1',
'default' => 'your-secret-key',
'required' => true,
'question' => 'Choose a secret API key, make sure to make a backup of your key in a secure location',
],
[
'name' => '_APP_DOMAIN',
'default' => 'localhost',
'required' => true,
'question' => 'Enter your Appwrite hostname',
],
[
'name' => '_APP_DOMAIN_TARGET',
'default' => 'localhost',
'required' => true,
'question' => "Enter a DNS A record hostname to serve as a CNAME for your custom domains.\nYou can use the same value as used for the Appwrite hostname.",
],
[
'name' => '_APP_REDIS_HOST',
'default' => 'redis',
'required' => false,
'question' => '',
],
[
'name' => '_APP_REDIS_PORT',
'default' => '6379',
'required' => false,
'question' => '',
],
[
'name' => '_APP_DB_HOST',
'default' => 'mariadb',
'required' => false,
'question' => '',
],
[
'name' => '_APP_DB_PORT',
'default' => '3306',
'required' => false,
'question' => '',
],
[
'name' => '_APP_DB_SCHEMA',
'default' => 'appwrite',
'required' => false,
'question' => '',
],
[
'name' => '_APP_DB_USER',
'default' => 'user',
'required' => false,
'question' => '',
],
[
'name' => '_APP_DB_PASS',
'default' => 'password',
'required' => false,
'question' => '',
],
[
'name' => '_APP_INFLUXDB_HOST',
'default' => 'influxdb',
'required' => false,
'question' => '',
],
[
'name' => '_APP_INFLUXDB_PORT',
'default' => '8086',
'required' => false,
'question' => '',
],
[
'name' => '_APP_STATSD_HOST',
'default' => 'telegraf',
'required' => false,
'question' => '',
],
[
'name' => '_APP_STATSD_PORT',
'default' => '8125',
'required' => false,
'question' => '',
],
[
'name' => '_APP_SMTP_HOST',
'default' => 'smtp',
'required' => false,
'question' => '',
],
[
'name' => '_APP_SMTP_PORT',
'default' => '25',
'required' => false,
'question' => '',
],
[
'name' => '_APP_STORAGE_LIMIT',
'default' => '100000000',
'required' => false,
'question' => '',
],
[
'name' => '_APP_FUNCTIONS_TIMEOUT',
'default' => '900',
'required' => false,
'question' => '',
],
[
'name' => '_APP_FUNCTIONS_CONTAINERS',
'default' => '10',
'required' => false,
'question' => '',
],
];

View file

@ -1,6 +1,6 @@
<?php
require_once __DIR__.'/init.php';
require_once __DIR__.'/../init.php';
use Utopia\App;
use Appwrite\Swoole\Request;
@ -460,8 +460,8 @@ App::get('/.well-known/acme-challenge')
$response->text($content);
}, ['request', 'response']);
include_once __DIR__ . '/controllers/shared/api.php';
include_once __DIR__ . '/controllers/shared/web.php';
include_once __DIR__ . '/shared/api.php';
include_once __DIR__ . '/shared/web.php';
foreach(Config::getParam('services', []) as $service) {
include_once $service['controller'];

View file

@ -63,7 +63,7 @@ $http->on('start', function (Server $http) use ($payloadSize) {
Files::load(__DIR__ . '/../public');
include __DIR__ . '/app.php';
include __DIR__ . '/controllers/general.php';
$domain = App::getEnv('_APP_DOMAIN', '');

View file

@ -67,6 +67,7 @@ Config::load('environments', __DIR__.'/config/environments.php');
Config::load('roles', __DIR__.'/config/roles.php'); // User roles and scopes
Config::load('scopes', __DIR__.'/config/scopes.php'); // User roles and scopes
Config::load('services', __DIR__.'/config/services.php'); // List of services
Config::load('variables', __DIR__.'/config/variables.php'); // List of env variables
Config::load('avatar-browsers', __DIR__.'/config/avatars/browsers.php');
Config::load('avatar-credit-cards', __DIR__.'/config/avatars/credit-cards.php');
Config::load('avatar-flags', __DIR__.'/config/avatars/flags.php');

View file

@ -18,8 +18,7 @@ if (file_exists(__DIR__.'/../vendor/autoload.php')) {
use Appwrite\Preloader\Preloader;
include 'init.php';
include 'app.php';
include __DIR__.'/controllers/general.php';
(new Preloader())
->paths(realpath(__DIR__ . '/../app/config'))

View file

@ -1,35 +1,14 @@
#!/bin/env php
<?php
require_once __DIR__.'/../init.php';
global $cli;
use Appwrite\ClamAV\Network;
use Appwrite\Storage\Device\Local;
use Appwrite\Storage\Storage;
use Utopia\App;
use Utopia\CLI\CLI;
use Utopia\CLI\Console;
use Utopia\Domains\Domain;
$cli = new CLI();
$cli
->task('ssl')
->desc('Validate server certificates')
->action(function () {
$domain = App::getEnv('_APP_DOMAIN', '');
Console::log('Issue a TLS certificate for master domain ('.$domain.') in 30 seconds.
Make sure your domain points to your server or restart to try again.');
ResqueScheduler::enqueueAt(\time() + 30, 'v1-certificates', 'CertificatesV1', [
'document' => [],
'domain' => $domain,
'validateTarget' => false,
'validateCNAME' => false,
]);
});
$cli
->task('doctor')
->desc('Validate server health')
@ -254,6 +233,4 @@ $cli
} catch (\Throwable $th) {
Console::error('Failed to check for a newer version'."\n");
}
});
$cli->run();
});

152
app/tasks/install.php Normal file
View file

@ -0,0 +1,152 @@
<?php
global $cli;
use Appwrite\Docker\Compose;
use Appwrite\Docker\Env;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\View;
$cli
->task('install')
->desc('Install Appwrite')
->action(function () {
/**
* 1. Start - DONE
* 2. Check for older setup and get older version - DONE
* 2.1 If older version is equal or bigger(?) than current version, **stop setup**
* 2.2. Get ENV vars - DONE
* 2.2.1 Fetch from older docker-compose.yml file
* 2.2.2 Fetch from older .env file (manually parse)
* 2.3 Use old ENV vars as default values
* 2.4 Ask for all required vars not given as CLI args and if in interactive mode
* Otherwise, just use default vars. - DONE
* 3. Ask user to backup important volumes, env vars, and SQL tables
* In th future we can try and automate this for smaller/medium size setups
* 4. Drop new docker-compose.yml setup (located inside the container, no network dependencies with appwrite.io) - DONE
* 5. Run docker-compose up -d - DONE
* 6. Run data migration
*/
$vars = Config::getParam('variables');
$path = '/usr/src/code/appwrite';
$version = null;
$defaultHTTPPort = '80';
$defaultHTTPSPort = '443';
Console::success('Starting Appwrite installation...');
// Create directory with write permissions
if (null !== $path && !\file_exists(\dirname($path))) {
if (!@\mkdir(\dirname($path), 0755, true)) {
Console::error('Can\'t create directory '.\dirname($path));
exit(1);
}
}
$data = @file_get_contents($path.'/docker-compose.yml');
if($data !== false) {
$compose = new Compose($data);
$appwrite = $compose->getService('appwrite');
$version = ($appwrite) ? $appwrite->getImageVersion() : $version;
$ports = $compose->getService('traefik')->getPorts();
if($version) {
foreach($compose->getServices() as $service) { // Fetch all env vars from previous compose file
if(!$service) {
continue;
}
$env = $service->getEnvironment()->list();
foreach ($env as $key => $value) {
foreach($vars as &$var) {
if($var['name'] === $key) {
$var['default'] = $value;
}
}
}
}
$data = @file_get_contents($path.'/.env');
if($data !== false) { // Fetch all env vars from previous .env file
$env = new Env($data);
foreach ($env->list() as $key => $value) {
foreach($vars as &$var) {
if($var['name'] === $key) {
$var['default'] = $value;
}
}
}
}
foreach ($ports as $key => $value) {
if($value === $defaultHTTPPort) {
$defaultHTTPPort = $key;
}
if($value === $defaultHTTPSPort) {
$defaultHTTPSPort = $key;
}
}
}
}
$httpPort = Console::confirm('Choose your server HTTP port: (default: '.$defaultHTTPPort.')');
$httpPort = ($httpPort) ? $httpPort : $defaultHTTPPort;
$httpsPort = Console::confirm('Choose your server HTTPS port: (default: '.$defaultHTTPSPort.')');
$httpsPort = ($httpsPort) ? $httpsPort : $defaultHTTPPort;
$input = [];
foreach($vars as $key => $var) {
if(!$var['required']) {
$input[$var['name']] = $var['default'];
continue;
}
$input[$var['name']] = Console::confirm($var['question'].' (default: \''.$var['default'].'\')');
if(empty($input[$key])) {
$input[$var['name']] = $var['default'];
}
}
$templateForCompose = new View(__DIR__.'/../views/install/compose.phtml');
$templateForEnv = new View(__DIR__.'/../views/install/env.phtml');
$templateForCompose
->setParam('httpPort', $httpPort)
->setParam('httpsPort', $httpsPort)
->setParam('version', APP_VERSION_STABLE)
;
$templateForEnv
->setParam('vars', $input)
;
if(!file_put_contents($path.'/docker-compose.yml', $templateForCompose->render(false))) {
Console::error('Failed to save Docker Compose file');
exit(1);
}
if(!file_put_contents($path.'/.env', $templateForEnv->render(false))) {
Console::error('Failed to save environment variables file');
exit(1);
}
$stdout = '';
$stderr = '';
//Console::execute("docker-compose -f {$path}.'/docker-compose.yml up -d --remove-orphans", null, $stdout, $stderr);
if ($stderr !== '') {
Console::error("Failed to install Appwrite dockers");
} else {
Console::success("Appwrite installed successfully");
}
});

View file

@ -1,18 +1,13 @@
#!/bin/env php
<?php
require_once __DIR__.'/../init.php';
global $register, $projectDB, $console;
global $cli, $register, $projectDB, $console;
use Utopia\Config\Config;
use Utopia\CLI\CLI;
use Utopia\CLI\Console;
use Appwrite\Database\Database;
use Appwrite\Database\Document;
use Appwrite\Database\Validator\Authorization;
$cli = new CLI();
$db = $register->get('db');
$callbacks = [
@ -152,9 +147,7 @@ function fixDocument(Document $document) {
->removeAttribute('$uid')
;
//Console::log('Switched from $uid to $id: '.$document->getCollection().'/'.$document->getId());
foreach($document as &$attr) {
foreach($document as &$attr) { // Handle child documents
if($attr instanceof Document) {
$attr = fixDocument($attr);
}
@ -172,7 +165,7 @@ function fixDocument(Document $document) {
}
$cli
->task('run')
->task('migrate')
->action(function () use ($console, $projectDB, $consoleDB, $callbacks) {
Console::success('Starting Data Migration');
@ -214,6 +207,4 @@ $cli
}
Console::success('Data Migration Completed');
});
$cli->run();
});

View file

@ -1,10 +1,8 @@
#!/bin/env php
<?php
require_once __DIR__.'/../init.php';
global $cli;
use Utopia\Config\Config;
use Utopia\CLI\CLI;
use Utopia\CLI\Console;
use Appwrite\Spec\Swagger2;
use Appwrite\SDK\SDK;
@ -19,8 +17,6 @@ use Appwrite\SDK\Language\Flutter;
use Appwrite\SDK\Language\Go;
use Appwrite\SDK\Language\Java;
$cli = new CLI();
$version = APP_VERSION_STABLE; // Server version
$warning = '**This SDK is compatible with Appwrite server version ' . $version . '. For older versions, please check previous releases.**';
@ -205,6 +201,4 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
}
exit();
});
$cli->run();
});

23
app/tasks/ssl.php Normal file
View file

@ -0,0 +1,23 @@
<?php
global $cli;
use Utopia\App;
use Utopia\CLI\Console;
$cli
->task('ssl')
->desc('Validate server certificates')
->action(function () {
$domain = App::getEnv('_APP_DOMAIN', '');
Console::log('Issue a TLS certificate for master domain ('.$domain.') in 30 seconds.
Make sure your domain points to your server or restart to try again.');
ResqueScheduler::enqueueAt(\time() + 30, 'v1-certificates', 'CertificatesV1', [
'document' => [],
'domain' => $domain,
'validateTarget' => false,
'validateCNAME' => false,
]);
});

View file

@ -0,0 +1,327 @@
<?php
$httpPort = $this->getParam('httpPort', '');
$httpsPort = $this->getParam('httpsPort', '');
$version = $this->getParam('version', '');
?>version: '3'
services:
traefik:
image: traefik:2.2
container_name: appwrite-traefik
command:
- --providers.file.directory=/storage/config
- --providers.file.watch=true
- --providers.docker=true
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
restart: unless-stopped
ports:
- <?php echo $httpPort; ?>:80
- <?php echo $httpsPort; ?>:443
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- appwrite-config:/storage/config:ro
- appwrite-certificates:/storage/certificates:ro
depends_on:
- appwrite
networks:
- gateway
- appwrite
appwrite:
image: appwrite/appwrite:<?php echo $version."\n"; ?>
container_name: appwrite
restart: unless-stopped
networks:
- appwrite
labels:
- traefik.http.routers.appwrite.rule=PathPrefix(`/`)
- traefik.http.routers.appwrite-secure.rule=PathPrefix(`/`)
- traefik.http.routers.appwrite-secure.tls=true
volumes:
- appwrite-uploads:/storage/uploads:rw
- appwrite-cache:/storage/cache:rw
- appwrite-config:/storage/config:rw
- appwrite-certificates:/storage/certificates:rw
- appwrite-functions:/storage/functions:rw
depends_on:
- mariadb
- redis
- clamav
- influxdb
environment:
- _APP_ENV
- _APP_OPTIONS_ABUSE
- _APP_OPTIONS_FORCE_HTTPS
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_INFLUXDB_HOST
- _APP_INFLUXDB_PORT
- _APP_STORAGE_LIMIT
- _APP_FUNCTIONS_TIMEOUT
- _APP_FUNCTIONS_CONTAINERS
appwrite-worker-usage:
image: appwrite/appwrite:<?php echo $version."\n"; ?>
entrypoint: worker-usage
container_name: appwrite-worker-usage
restart: unless-stopped
networks:
- appwrite
depends_on:
- redis
- telegraf
environment:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_STATSD_HOST
- _APP_STATSD_PORT
appwrite-worker-audits:
image: appwrite/appwrite:<?php echo $version."\n"; ?>
entrypoint: worker-audits
container_name: appwrite-worker-audits
restart: unless-stopped
networks:
- appwrite
depends_on:
- redis
- mariadb
environment:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
appwrite-worker-webhooks:
image: appwrite/appwrite:<?php echo $version."\n"; ?>
entrypoint: worker-webhooks
container_name: appwrite-worker-webhooks
restart: unless-stopped
networks:
- appwrite
depends_on:
- redis
- mariadb
environment:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
appwrite-worker-tasks:
image: appwrite/appwrite:<?php echo $version."\n"; ?>
entrypoint: worker-tasks
container_name: appwrite-worker-tasks
restart: unless-stopped
networks:
- appwrite
depends_on:
- redis
- mariadb
environment:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
appwrite-worker-deletes:
image: appwrite/appwrite:<?php echo $version."\n"; ?>
entrypoint: worker-deletes
container_name: appwrite-worker-deletes
restart: unless-stopped
networks:
- appwrite
depends_on:
- redis
- mariadb
volumes:
- appwrite-uploads:/storage/uploads:rw
- appwrite-cache:/storage/cache:rw
environment:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
appwrite-worker-certificates:
image: appwrite/appwrite:<?php echo $version."\n"; ?>
entrypoint: worker-certificates
container_name: appwrite-worker-certificates
restart: unless-stopped
networks:
- appwrite
depends_on:
- redis
- mariadb
volumes:
- appwrite-config:/storage/config:rw
- appwrite-certificates:/storage/certificates:rw
environment:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
appwrite-worker-functions:
image: appwrite/appwrite:<?php echo $version."\n"; ?>
entrypoint: worker-functions
container_name: appwrite-worker-functions
restart: unless-stopped
networks:
- appwrite
depends_on:
- redis
- mariadb
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /tmp:/tmp:rw
- appwrite-functions:/storage/functions:rw
environment:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_FUNCTIONS_TIMEOUT
- _APP_FUNCTIONS_CONTAINERS
appwrite-worker-mails:
image: appwrite/appwrite:<?php echo $version."\n"; ?>
entrypoint: worker-mails
container_name: appwrite-worker-mails
restart: unless-stopped
networks:
- appwrite
depends_on:
- redis
- smtp
environment:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_SMTP_HOST
- _APP_SMTP_PORT
appwrite-schedule:
image: appwrite/appwrite:<?php echo $version."\n"; ?>
entrypoint: schedule
container_name: appwrite-schedule
restart: unless-stopped
networks:
- appwrite
depends_on:
- redis
environment:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
mariadb:
image: appwrite/mariadb:1.0.3 # fix issues when upgrading using: mysql_upgrade -u root -p
container_name: appwrite-mariadb
restart: unless-stopped
networks:
- appwrite
volumes:
- appwrite-mariadb:/var/lib/mysql:rw
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=rootsecretpassword
- MYSQL_DATABASE=appwrite
- MYSQL_USER=user
- MYSQL_PASSWORD=password
command: 'mysqld --innodb-flush-method=fsync'
smtp:
image: appwrite/smtp:1.0.1
container_name: appwrite-smtp
restart: unless-stopped
networks:
- appwrite
environment:
- MAILNAME=appwrite
- RELAY_NETWORKS=:192.168.0.0/24:10.0.0.0/16
redis:
image: redis:5.0
container_name: appwrite-redis
restart: unless-stopped
networks:
- appwrite
volumes:
- appwrite-redis:/data:rw
clamav:
image: appwrite/clamav:1.0.12
container_name: appwrite-clamav
restart: unless-stopped
networks:
- appwrite
volumes:
- appwrite-uploads:/storage/uploads
influxdb:
image: influxdb:1.6
container_name: appwrite-influxdb
restart: unless-stopped
networks:
- appwrite
volumes:
- appwrite-influxdb:/var/lib/influxdb:rw
telegraf:
image: appwrite/telegraf:1.0.0
container_name: appwrite-telegraf
restart: unless-stopped
networks:
- appwrite
networks:
gateway:
appwrite:
volumes:
appwrite-mariadb:
appwrite-redis:
appwrite-cache:
appwrite-uploads:
appwrite-certificates:
appwrite-functions:
appwrite-influxdb:
appwrite-chronograf:
appwrite-config:

View file

@ -0,0 +1,8 @@
<?php
$vars = $this->getParam('vars');
foreach ($vars as $key => $value) {
echo $key.'='.$value."\n";
}
?>

View file

@ -1,3 +1,3 @@
#!/bin/sh
php /usr/src/code/app/tasks/init.php doctor
php /usr/src/code/app/cli.php doctor $@

3
bin/install Executable file
View file

@ -0,0 +1,3 @@
#!/bin/sh
php /usr/src/code/app/cli.php install $@

View file

@ -1,3 +1,3 @@
#!/bin/sh
php /usr/src/code/app/tasks/migrate.php run
php /usr/src/code/app/cli.php migrate $@

3
bin/ssl Executable file
View file

@ -0,0 +1,3 @@
#!/bin/sh
php /usr/src/code/app/cli.php ssl $@

View file

@ -1,3 +1,3 @@
#!/bin/sh
/usr/src/code/vendor/bin/phpunit --configuration /usr/src/code/phpunit.xml
/usr/src/code/vendor/bin/phpunit --configuration /usr/src/code/phpunit.xml $@

View file

@ -20,7 +20,7 @@ ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
//trigger_error('hide errors in prod', E_USER_NOTICE);
include __DIR__ . '/../app/app.php';
include __DIR__ . '/../app/controllers/general.php';
$app = new App('Asia/Tel_Aviv');

View file

@ -0,0 +1,73 @@
<?php
namespace Appwrite\Docker;
use Appwrite\Docker\Compose\Service;
use Exception;
class Compose
{
/**
* @var array
*/
protected $compose = [];
/**
* @var string $data
*/
public function __construct(string $data)
{
$this->compose = yaml_parse($data);
$this->compose['services'] = (isset($this->compose['services']) && is_array($this->compose['services']))
? $this->compose['services'] : [];
foreach ($this->compose['services'] as $key => &$service) {
$service = new Service($service);
}
}
/**
* @return array
*/
public function getVersion(): string
{
return (isset($this->compose['version'])) ? $this->compose['version'] : '';
}
/**
* @return Service[]
*/
public function getServices(): array
{
return $this->compose['services'];
}
/**
* @return Service
*/
public function getService(string $name): Service
{
if(!isset($this->compose['services'][$name])) {
throw new Exception('Service not found');
}
return $this->compose['services'][$name];
}
/**
* @return array
*/
public function getNetworks(): array
{
return (isset($this->compose['networks'])) ? array_keys($this->compose['networks']) : [];
}
/**
* @return array
*/
public function getVolumes(): array
{
return (isset($this->compose['volumes'])) ? array_keys($this->compose['volumes']) : [];
}
}

View file

@ -0,0 +1,75 @@
<?php
namespace Appwrite\Docker\Compose;
use Appwrite\Docker\Env;
class Service
{
/**
* @var array
*/
protected $service = [];
/**
* @var string $path
*/
public function __construct(array $service)
{
$this->service = $service;
$ports = (isset($this->service['ports']) && is_array($this->service['ports'])) ? $this->service['ports'] : [];
$this->service['ports'] = [];
array_walk($ports, function(&$value, &$key) {
$split = explode(':', $value);
$this->service['ports'][
(isset($split[0])) ? $split[0] : ''
] = (isset($split[1])) ? $split[1] : '';
});
$this->service['environment'] = (isset($this->service['environment']) && is_array($this->service['environment'])) ? $this->service['environment'] : [];
$this->service['environment'] = new Env(implode("\n", $this->service['environment']));
}
/**
* @return string
*/
public function getContainerName(): string
{
return (isset($this->service['container_name'])) ? $this->service['container_name'] : '';
}
/**
* @return string
*/
public function getImage(): string
{
return (isset($this->service['image'])) ? $this->service['image'] : '';
}
/**
* @return string
*/
public function getImageVersion(): string
{
$image = $this->getImage();
return substr($image, strpos($image, ':')+1);
}
/**
* @return Env
*/
public function getEnvironment(): Env
{
return $this->service['environment'];
}
/**
* @return array
*/
public function getPorts(): array
{
return $this->service['ports'];
}
}

View file

@ -0,0 +1,79 @@
<?php
namespace Appwrite\Docker;
use Exception;
class Env
{
/**
* @var array
*/
protected $vars = [];
/**
* @var string $data
*/
public function __construct(string $data)
{
$data = explode("\n", $data);
foreach($data as &$row) {
$row = explode('=', $row);
$key = (isset($row[0])) ? trim($row[0]) : null;
$value = (isset($row[1])) ? trim($row[1]) : null;
if($key) {
$this->vars[$key] = $value;
}
}
}
/**
* @param string $key
* @param mixed $value
*
* @return $this
*/
public function setVar(string $key, $value): self
{
$this->vars[$key] = $value;
return $this;
}
/**
* @param string $key
*
* @return mixed|null
*/
public function getVar(string $key): string
{
return (isset($this->vars[$key])) ? $this->vars[$key] : '';
}
/**
* Get All Vars
*
* @return array
*/
public function list(): array
{
return $this->vars;
}
/**
* @return string
*/
public function export(): string
{
$output = '';
foreach ($this->vars as $key => $value) {
$output .= $key.'='.$value."\n";
}
return $output;
}
}

View file

@ -0,0 +1,3 @@
_APP_X=value1
_APP_Y=value2
_APP_Z = value3

View file

@ -0,0 +1,409 @@
version: '3'
services:
traefik:
image: traefik:2.2
container_name: appwrite-traefik
command:
- --log.level=DEBUG
- --api.insecure=true
- --providers.file.directory=/storage/config
- --providers.file.watch=true
- --providers.docker=true
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --accesslog=true
restart: unless-stopped
ports:
- 2080:80
- 2443:443
- 8080:8080
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- appwrite-config:/storage/config:ro
- appwrite-certificates:/storage/certificates:ro
depends_on:
- appwrite
networks:
- gateway
- appwrite
appwrite:
container_name: appwrite
build:
context: .
args:
- TESTING=true
- VERSION=dev
restart: unless-stopped
ports:
- 9501:80
networks:
- appwrite
labels:
- traefik.http.routers.appwrite.rule=PathPrefix(`/`)
- traefik.http.routers.appwrite-secure.rule=PathPrefix(`/`)
- traefik.http.routers.appwrite-secure.tls=true
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- appwrite-uploads:/storage/uploads:rw
- appwrite-cache:/storage/cache:rw
- appwrite-config:/storage/config:rw
- appwrite-certificates:/storage/certificates:rw
- appwrite-functions:/storage/functions:rw
- ./phpunit.xml:/usr/src/code/phpunit.xml
- ./tests:/usr/src/code/tests
- ./app:/usr/src/code/app
# - ./vendor:/usr/src/code/vendor
- ./docs:/usr/src/code/docs
- ./public:/usr/src/code/public
- ./src:/usr/src/code/src
- ./debug:/tmp
depends_on:
- mariadb
- redis
- clamav
- influxdb
environment:
- _APP_ENV
- _APP_OPTIONS_ABUSE
- _APP_OPTIONS_FORCE_HTTPS
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_INFLUXDB_HOST
- _APP_INFLUXDB_PORT
- _APP_STORAGE_LIMIT
- _APP_FUNCTIONS_TIMEOUT
- _APP_FUNCTIONS_CONTAINERS
appwrite-worker-usage:
entrypoint: worker-usage
container_name: appwrite-worker-usage
build:
context: .
restart: unless-stopped
networks:
- appwrite
depends_on:
- redis
- telegraf
environment:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_STATSD_HOST
- _APP_STATSD_PORT
appwrite-worker-audits:
entrypoint: worker-audits
container_name: appwrite-worker-audits
build:
context: .
restart: unless-stopped
networks:
- appwrite
depends_on:
- redis
- mariadb
environment:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
appwrite-worker-webhooks:
entrypoint: worker-webhooks
container_name: appwrite-worker-webhooks
build:
context: .
restart: unless-stopped
networks:
- appwrite
depends_on:
- redis
- mariadb
environment:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
appwrite-worker-tasks:
entrypoint: worker-tasks
container_name: appwrite-worker-tasks
build:
context: .
restart: unless-stopped
networks:
- appwrite
depends_on:
- redis
- mariadb
environment:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
appwrite-worker-deletes:
entrypoint: worker-deletes
container_name: appwrite-worker-deletes
build:
context: .
restart: unless-stopped
networks:
- appwrite
depends_on:
- redis
- mariadb
volumes:
- appwrite-uploads:/storage/uploads:rw
- appwrite-cache:/storage/cache:rw
environment:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
appwrite-worker-certificates:
entrypoint: worker-certificates
container_name: appwrite-worker-certificates
build:
context: .
restart: unless-stopped
networks:
- appwrite
depends_on:
- redis
- mariadb
volumes:
- appwrite-config:/storage/config:rw
- appwrite-certificates:/storage/certificates:rw
environment:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
appwrite-worker-functions:
entrypoint: worker-functions
container_name: appwrite-worker-functions
build:
context: .
restart: unless-stopped
networks:
- appwrite
depends_on:
- redis
- mariadb
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /tmp:/tmp:rw
- appwrite-functions:/storage/functions:rw
environment:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_FUNCTIONS_TIMEOUT
- _APP_FUNCTIONS_CONTAINERS
appwrite-worker-mails:
entrypoint: worker-mails
container_name: appwrite-worker-mails
build:
context: .
restart: unless-stopped
networks:
- appwrite
depends_on:
- redis
- maildev
# - smtp
environment:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_SMTP_HOST
- _APP_SMTP_PORT
appwrite-schedule:
entrypoint: schedule
container_name: appwrite-schedule
build:
context: .
restart: unless-stopped
networks:
- appwrite
depends_on:
- redis
environment:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
mariadb:
image: appwrite/mariadb:1.0.3 # fix issues when upgrading using: mysql_upgrade -u root -p
container_name: appwrite-mariadb
restart: unless-stopped
networks:
- appwrite
volumes:
- appwrite-mariadb:/var/lib/mysql:rw
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=rootsecretpassword
- MYSQL_DATABASE=appwrite
- MYSQL_USER=user
- MYSQL_PASSWORD=password
command: 'mysqld --innodb-flush-method=fsync'
maildev:
image: djfarrelly/maildev
container_name: appwrite-maildev
restart: unless-stopped
ports:
- '1080:80'
networks:
- appwrite
# smtp:
# image: appwrite/smtp:1.0.1
# container_name: appwrite-smtp
# restart: unless-stopped
# networks:
# - appwrite
# environment:
# - MAILNAME=appwrite
# - RELAY_NETWORKS=:192.168.0.0/24:10.0.0.0/16
redis:
image: redis:5.0
container_name: appwrite-redis
restart: unless-stopped
networks:
- appwrite
volumes:
- appwrite-redis:/data:rw
clamav:
image: appwrite/clamav:1.0.12
container_name: appwrite-clamav
restart: unless-stopped
networks:
- appwrite
volumes:
- appwrite-uploads:/storage/uploads
influxdb:
image: influxdb:1.6
container_name: appwrite-influxdb
restart: unless-stopped
networks:
- appwrite
volumes:
- appwrite-influxdb:/var/lib/influxdb:rw
telegraf:
image: appwrite/telegraf:1.0.0
container_name: appwrite-telegraf
restart: unless-stopped
networks:
- appwrite
# redis-commander:
# image: rediscommander/redis-commander:latest
# restart: unless-stopped
# networks:
# - appwrite
# environment:
# - REDIS_HOSTS=redis
# ports:
# - "8081:8081"
# resque:
# image: registry.gitlab.com/appwrite/appwrite/resque-web:v1.0.2
# restart: unless-stopped
# networks:
# - appwrite
# ports:
# - "5678:5678"
# environment:
# - RESQUE_WEB_HOST=redis
# - RESQUE_WEB_PORT=6379
# - RESQUE_WEB_HTTP_BASIC_AUTH_USER=user
# - RESQUE_WEB_HTTP_BASIC_AUTH_PASSWORD=password
# chronograf:
# image: chronograf:1.5
# container_name: appwrite-chronograf
# restart: unless-stopped
# networks:
# - appwrite
# volumes:
# - appwrite-chronograf:/var/lib/chronograf
# ports:
# - "8888:8888"
# environment:
# - INFLUXDB_URL=http://influxdb:8086
# - KAPACITOR_URL=http://kapacitor:9092
# - AUTH_DURATION=48h
# - TOKEN_SECRET=duperduper5674829!jwt
# - GH_CLIENT_ID=d86f7145a41eacfc52cc
# - GH_CLIENT_SECRET=9e0081062367a2134e7f2ea95ba1a32d08b6c8ab
# - GH_ORGS=appwrite
# webgrind:
# image: 'jokkedk/webgrind:latest'
# volumes:
# - './debug:/tmp'
# ports:
# - '3001:80'
networks:
gateway:
appwrite:
volumes:
appwrite-mariadb:
appwrite-redis:
appwrite-cache:
appwrite-uploads:
appwrite-certificates:
appwrite-functions:
appwrite-influxdb:
appwrite-chronograf:
appwrite-config:

View file

@ -0,0 +1,59 @@
<?php
namespace Appwrite\Tests;
use Appwrite\Docker\Compose;
use Exception;
use PHPUnit\Framework\TestCase;
class ComposeTest extends TestCase
{
/**
* @var Compose
*/
protected $object = null;
public function setUp()
{
$data = @file_get_contents(__DIR__.'/../../resources/docker/docker-compose.yml');
if($data === false) {
throw new Exception('Failed to read compose file');
}
$this->object = new Compose($data);
}
public function tearDown()
{
}
public function testVersion()
{
$this->assertEquals('3', $this->object->getVersion());
}
public function testServices()
{
$this->assertCount(17, $this->object->getServices());
$this->assertEquals('appwrite-telegraf', $this->object->getService('telegraf')->getContainerName());
$this->assertEquals('appwrite', $this->object->getService('appwrite')->getContainerName());
$this->assertEquals('', $this->object->getService('appwrite')->getImageVersion());
$this->assertEquals('2.2', $this->object->getService('traefik')->getImageVersion());
$this->assertEquals(['2080' => '80', '2443' => '443', '8080' => '8080'], $this->object->getService('traefik')->getPorts());
}
public function testNetworks()
{
$this->assertCount(2, $this->object->getNetworks());
}
public function testVolumes()
{
$this->assertCount(9, $this->object->getVolumes());
$this->assertEquals('appwrite-mariadb', $this->object->getVolumes()[0]);
$this->assertEquals('appwrite-redis', $this->object->getVolumes()[1]);
$this->assertEquals('appwrite-cache', $this->object->getVolumes()[2]);
}
}

View file

@ -0,0 +1,49 @@
<?php
namespace Appwrite\Tests;
use Appwrite\Docker\Env;
use Exception;
use PHPUnit\Framework\TestCase;
class EnvTest extends TestCase
{
/**
* @var Env
*/
protected $object = null;
public function setUp()
{
$data = @file_get_contents(__DIR__.'/../../resources/docker/.env');
if($data === false) {
throw new Exception('Failed to read compose file');
}
$this->object = new Env($data);
}
public function tearDown()
{
}
public function testVars()
{
$this->object->setVar('_APP_TEST', 'value4');
$this->assertEquals('value1', $this->object->getVar('_APP_X'));
$this->assertEquals('value2', $this->object->getVar('_APP_Y'));
$this->assertEquals('value3', $this->object->getVar('_APP_Z'));
$this->assertEquals('value4', $this->object->getVar('_APP_TEST'));
}
public function testExport()
{
$this->assertEquals("_APP_X=value1
_APP_Y=value2
_APP_Z=value3
", $this->object->export());
}
}