From c1f0d5702713bb724cace7731f6717e116c653d8 Mon Sep 17 00:00:00 2001 From: Joshua Avalon Date: Tue, 1 Jan 2019 19:17:17 +0800 Subject: [PATCH] Initial Commit --- .gitattributes | 1 + .travis.yml | 26 ++ LICENSE | 201 ++++++++++++++++ README.md | 11 + api/Dockerfile | 29 +++ api/root/bootstrap.php | 103 ++++++++ api/root/run.sh | 26 ++ api/root/usr/local/etc/php/conf.d/uploads.ini | 5 + api/root/var/www/html/config/api.php | 223 ++++++++++++++++++ app/Dockerfile | 20 ++ app/config.js | 33 +++ app/root/etc/nginx/conf.d/default.conf | 18 ++ app/root/etc/nginx/general.conf | 31 +++ app/root/etc/nginx/nginx.conf | 31 +++ app/root/etc/services.d/nginx/run | 3 + docker-compose.yml | 27 +++ 16 files changed, 788 insertions(+) create mode 100644 .gitattributes create mode 100644 .travis.yml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 api/Dockerfile create mode 100644 api/root/bootstrap.php create mode 100644 api/root/run.sh create mode 100644 api/root/usr/local/etc/php/conf.d/uploads.ini create mode 100644 api/root/var/www/html/config/api.php create mode 100644 app/Dockerfile create mode 100644 app/config.js create mode 100644 app/root/etc/nginx/conf.d/default.conf create mode 100644 app/root/etc/nginx/general.conf create mode 100644 app/root/etc/nginx/nginx.conf create mode 100644 app/root/etc/services.d/nginx/run create mode 100644 docker-compose.yml diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..ee4a71c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,26 @@ +language: minimal + +jobs: + include: + - name: app + script: + - docker build --tag "${DOCKER_IMAGE_APP}:latest" app + before_deploy: + - echo "$DOCKER_PASS" | docker login -u "$DOCKER_USER" --password-stdin + - if [ -n "$TRAVIS_TAG" ]; then docker tag "${DOCKER_IMAGE_APP}:latest" "${DOCKER_IMAGE_APP}:${$TRAVIS_TAG}"; fi + deploy: + provider: script + script: docker push "${DOCKER_IMAGE_APP}:latest" && if [ -n "$TRAVIS_TAG" ]; then docker push "${DOCKER_IMAGE_APP}:${TRAVIS_TAG}"; fi + on: + branch: master + - name: api + script: + - docker build --tag "${DOCKER_IMAGE_API}:latest" api + before_deploy: + - echo "$DOCKER_PASS" | docker login -u "$DOCKER_USER" --password-stdin + - if [ -n "$TRAVIS_TAG" ]; then docker tag "${DOCKER_IMAGE_API}:latest" "${DOCKER_IMAGE_API}:${$TRAVIS_TAG}"; fi + deploy: + provider: script + script: docker push "${DOCKER_IMAGE_API}:latest" && if [ -n "$TRAVIS_TAG" ]; then docker push "${DOCKER_IMAGE_API}:${TRAVIS_TAG}"; fi + on: + branch: master diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4e58397 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018 Joshua Avalon + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..5c9b8f3 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# directus + +[![License][license_md]][license] +[![Travis CI][travis_ci]][travis] + +Docker image for Directus. + +[license]: https://github.com/joshava/directus/blob/master/LICENSE +[license_md]: https://img.shields.io/github/license/joshava/directus.svg +[travis]: https://travis-ci.org/joshava/directus +[travis_ci]: https://img.shields.io/travis/joshava/directus.svg diff --git a/api/Dockerfile b/api/Dockerfile new file mode 100644 index 0000000..81a9bb7 --- /dev/null +++ b/api/Dockerfile @@ -0,0 +1,29 @@ +FROM php:7-apache + +ARG VERSION=v2.0.13 + +RUN sed -i 's#/var/www/html#'/var/www/html/public'#g' /etc/apache2/sites-available/000-default.conf + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + git \ + zip \ + libpng-dev \ + libmagickwand-dev \ + netcat && \ + git clone -b $VERSION https://github.com/directus/api.git /var/www/html && \ + pecl install imagick && \ + docker-php-ext-enable imagick && \ + rm -r /var/lib/apt/lists/* + +RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ +RUN docker-php-ext-install pdo_mysql mbstring gd + +COPY root/ / + +RUN chown -R www-data:www-data /var/www/html && \ + chmod +x /run.sh + +RUN a2enmod rewrite + +CMD ["/run.sh"] diff --git a/api/root/bootstrap.php b/api/root/bootstrap.php new file mode 100644 index 0000000..d03383e --- /dev/null +++ b/api/root/bootstrap.php @@ -0,0 +1,103 @@ + PDO::ERRMODE_EXCEPTION + ]); +} catch (PDOException $e) { + write(""); + write(" ERROR: Database connection failed."); + write(" " . $e->getMessage()); + write(""); + exit(1); +} + +// Check if we need to install + +$install = true; + +try { + $statement = $connection->prepare("SHOW TABLES"); + $statement->execute(); + $tables = $statement->fetchAll(); + foreach ($tables as $table) { + $name = strtolower($table[0]); + if (substr($name, 0, 9) === "directus_") { + $install = false; + break; + } + } +} catch (PDOException $e) { + write(""); + write(" ERROR: Failed to list database tables."); + write(" " . $e->getMessage()); + write(""); + exit(1); +} + +// Initialize + +if ($install) { + + $admin_email = getenv("ADMIN_EMAIL"); + if (!$admin_email) { + write(""); + write(" ERROR: Missing ADMIN_EMAIL environment variable"); + write(""); + exit(1); + } + + $admin_password_generated = false; + $admin_password = getenv("ADMIN_PASSWORD"); + if (!$admin_password) { + $admin_password = substr(md5(uniqid("directus")), 0, 8); + $admin_password_generated = true; + } + + write("Installing database..."); + passthru("/var/www/html/bin/directus install:database"); + + write("Installing data..."); + passthru("/var/www/html/bin/directus install:install -e \"" . $admin_email . "\" -p \"" . $admin_password . "\" -t \"Directus\""); + + write(""); + write(" Directus database installed."); + if ($admin_password_generated) { + write(""); + write(" The credentials for admin account are:"); + write(""); + write(" Email: " . $admin_email); + write(" Password: " . $admin_password); + write(""); + } + write(""); + +} diff --git a/api/root/run.sh b/api/root/run.sh new file mode 100644 index 0000000..3e0b15c --- /dev/null +++ b/api/root/run.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +set -e; + +db_is_up() { + nc -z "${DATABASE_HOST:-database}" "${DATABASE_PORT:-3306}" >/dev/null 2>&1 +} + +RETRY_COUNT=0 +RETRIES=${DATABASE_WAIT_TIMEOUT:-30} +until db_is_up || [ $RETRY_COUNT -eq $RETRIES ] +do + echo "!" + sleep 1s + RETRY_COUNT=$((RETRY_COUNT+1)) +done + +if [ $RETRY_COUNT -eq $RETRIES ] +then + echo "exit" + exit 1 +fi + +php /bootstrap.php + +apache2-foreground diff --git a/api/root/usr/local/etc/php/conf.d/uploads.ini b/api/root/usr/local/etc/php/conf.d/uploads.ini new file mode 100644 index 0000000..2e4f6f5 --- /dev/null +++ b/api/root/usr/local/etc/php/conf.d/uploads.ini @@ -0,0 +1,5 @@ +file_uploads = On +memory_limit = 10M +upload_max_filesize = 10M +post_max_size = 10M +max_execution_time = 600 diff --git a/api/root/var/www/html/config/api.php b/api/root/var/www/html/config/api.php new file mode 100644 index 0000000..abd7c17 --- /dev/null +++ b/api/root/var/www/html/config/api.php @@ -0,0 +1,223 @@ + $value) { + if (substr($key, 0, strlen($prefix)) === $prefix) { + $keys[] = $key; + } + } + return $keys; + } +} + +/** + * Reads the configuration + */ +if (!function_exists("api_config_read")) { + function api_config_read() { + $config = [ + 'app' => [ + 'env' => getenvs('APP_ENV', 'production'), + 'timezone' => getenvs('APP_TIMEZONE', 'America/New_York'), + ], + + 'settings' => [ + 'logger' => [ + 'path' => getenvs('SETTINGS_LOGGER_PATH', __DIR__ . '/logs/app.log'), + ], + ], + + 'database' => [ + 'type' => getenvs('DATABASE_TYPE', 'mysql'), + 'host' => getenvs('DATABASE_HOST', 'localhost'), + 'port' => getenvi('DATABASE_PORT', 3306), + 'name' => getenvs('DATABASE_NAME', 'directus'), + 'username' => getenvs('DATABASE_USERNAME', 'root'), + 'password' => getenvs('DATABASE_PASSWORD', 'root'), + 'engine' => getenvs('DATABASE_ENGINE', 'InnoDB'), + 'charset' => getenvs('DATABASE_CHARSET', 'utf8mb4') + ], + + 'cache' => [ + 'enabled' => getenvb('CACHE_ENABLED', false), + 'response_ttl' => getenvi('CACHE_RESPONSE_TTL', 3600), // seconds + ], + + 'storage' => [ + 'adapter' => getenvs('STORAGE_ADAPTER', 'local'), + 'root' => getenvs('STORAGE_ROOT', 'public/uploads/_/originals'), + 'root_url' => getenvs('STORAGE_ROOT_URL', '/uploads/_/originals'), + 'thumb_root' => getenvs('STORAGE_THUMB_URL', 'public/uploads/_/thumbnails'), + 'key' => getenvs('STORAGE_KEY', 's3-key'), + 'secret' => getenvs('STORAGE_SECRET', 's3-secret'), + 'region' => getenvs('STORAGE_REGION', 'us-east-1'), + 'version' => getenvs('STORAGE_VERSION', 'latest'), + 'bucket' => getenvs('STORAGE_BUCKET', 'directus'), + ], + + 'mail' => [ + 'default' => [ + 'transport' => getenvs('MAIL_DEFAULT_TRANSPORT', 'sendmail'), + 'from' => getenvs('MAIL_DEFAULT_FROM', 'admin@example.com') + ], + ], + + 'cors' => [ + 'enabled' => getenvb('CORS_ENABLED', true), + 'origin' => ['*'], + 'methods' => [ + 'GET', + 'POST', + 'PUT', + 'PATCH', + 'DELETE', + 'HEAD', + ], + 'headers' => [], + 'exposed_headers' => [], + 'max_age' => getenvi('CORS_MAX_AGE', null), // in seconds + 'credentials' => getenvs('CORS_CREDENTIALS', false), + ], + + 'rate_limit' => [ + 'enabled' => getenvb('RATE_LIMIT_ENABLED', false), + 'limit' => getenvi('RATE_LIMIT_LIMIT', 100), // number of request + 'interval' => getenvi('RATE_LIMIT_INTERVAL', 60), // seconds + 'adapter' => getenvs('RATE_LIMIT_ADAPTER', 'redis'), + 'host' => getenvs('RATE_LIMIT_HOST', '127.0.0.1'), + 'port' => getenvi('RATE_LIMIT_PORT', 6379), + 'timeout' => getenvi('RATE_LIMIT_TIMEOUT', 10) + ], + + 'hooks' => [], + + 'filters' => [], + + 'feedback' => [ + 'token' => getenvs('FEEDBACK_TOKEN', 'a-kind-of-unique-token'), + 'login' => getenvb('FEEDBACK_LOGIN', true) + ], + + 'tableBlacklist' => [], + + 'auth' => [ + 'secret_key' => getenvs('AUTH_SECRET_KEY', ''), + 'public_key' => getenvs('AUTH_PUBLIC_KEY', ''), + 'social_providers' => [ + ] + ], + ]; + + $endpoint = getenvs('STORAGE_ENDPOINT', false); + if ($endpoint !== false) { + $config['storage']['endpoint'] = $endpoint; + } + + if (sizeof(getenvk('AUTH_OKTA_')) > 0) { + $config['auth']['social_providers']['okta'] = [ + 'client_id' => getenvs('AUTH_OKTA_CLIENT_ID', ''), + 'client_secret' => getenvs('AUTH_OKTA_CLIENT_SECRET', ''), + 'base_url' => getenvs('AUTH_OKTA_BASE_URL', 'https://dev-000000.oktapreview.com/oauth2/default') + ]; + } + + if (sizeof(getenvk('AUTH_GITHUB_')) > 0) { + $config['auth']['social_providers']['github'] = [ + 'client_id' => getenvs('AUTH_GITHUB_CLIENT_ID', ''), + 'client_secret' => getenvs('AUTH_GITHUB_CLIENT_SECRET', ''), + ]; + } + + if (sizeof(getenvk('AUTH_FACEBOOK_')) > 0) { + $config['auth']['social_providers']['facebook'] = [ + 'client_id' => getenvs('AUTH_FACEBOOK_CLIENT_ID', ''), + 'client_secret' => getenvs('AUTH_FACEBOOK_CLIENT_SECRET', ''), + 'graph_api_version' => getenvs('AUTH_FACEBOOK_GRAPH_API_VERSION', 'v2.8'), + ]; + } + + if (sizeof(getenvk('AUTH_GOOGLE_')) > 0) { + $config['auth']['social_providers']['google'] = [ + 'client_id' => getenvs('AUTH_GOOGLE_CLIENT_ID', ''), + 'client_secret' => getenvs('AUTH_GOOGLE_CLIENT_SECRET', ''), + 'hosted_domain' => getenvs('AUTH_GOOGLE_HOSTED_DOMAIN', '*'), + ]; + } + + if (sizeof(getenvk('AUTH_TWITTER_')) > 0) { + $config['auth']['social_providers']['twitter'] = [ + 'identifier' => getenvs('AUTH_TWITTER_IDENTIFIER', ''), + 'secret' => getenvs('AUTH_TWITTER_SECRET', ''), + ]; + } + + $pool = getenvk('CACHE_POOL_'); + if (sizeof($pool) > 0) { + $value = []; + foreach ($pool as $key) { + $name = strtolower(substr($key, strlen('CACHE_POOL_'))); + $value[$name] = getenvs($key, ''); + } + $config['cache']['pool'] = $value; + } + + return $config; + } +} + +return api_config_read(); diff --git a/app/Dockerfile b/app/Dockerfile new file mode 100644 index 0000000..e430f77 --- /dev/null +++ b/app/Dockerfile @@ -0,0 +1,20 @@ +FROM alpine + +ARG VERSION=v7.0.13 + +ADD https://github.com/just-containers/s6-overlay/releases/download/v1.21.7.0/s6-overlay-amd64.tar.gz /tmp/ +RUN tar xzf /tmp/s6-overlay-amd64.tar.gz -C / + +RUN apk add --no-cache nginx && \ + ln -sf /dev/stdout /var/log/nginx/access.log \ + ln -sf /dev/stderr /var/log/nginx/error.log + +COPY root/ / + +WORKDIR /directus + +RUN apk add --no-cache git && \ + git clone -b $VERSION https://github.com/directus/app.git . && \ + mv config_example.js config.js + +ENTRYPOINT ["/init"] diff --git a/app/config.js b/app/config.js new file mode 100644 index 0000000..792db64 --- /dev/null +++ b/app/config.js @@ -0,0 +1,33 @@ +/* eslint-disable */ + +(function directusConfig() { + const config = { + // The API URLs the user can connect to using this instance of the application. + // Object values are used as project name in the app + // Don't forget to add the API environment! + api: { + "https://demo-api.directus.app/_/": "Directus Demo API" + }, + + // Allow the user to connect to any API by entering a URL in a text field + // instead of selecting from a dropdown + allowOtherAPI: false, + + // Controls the way the application routes. By default, routing is done using + // hashes (#) to ensure the app works without any server url rewrites. + // + // If you're using the application and have the correct URL rewrites in place + // (everything to /index.html), you can change this to "history" to make + // the urls in the app a little prettier + routerMode: "history", // hash | history + + // When using history mode, the application will make all the routes "pretty" + // by using absolute paths. If you are serving the application from a folder + // like /admin, this will cause the routes to be wrong (eg /collection instead + // of /admin/collections). To combat this, set the routerBaseUrl to the path + // you're serving the application from + routerBaseUrl: "/" + }; + + window.__DirectusConfig__ = config; +})(); diff --git a/app/root/etc/nginx/conf.d/default.conf b/app/root/etc/nginx/conf.d/default.conf new file mode 100644 index 0000000..fe3f9ba --- /dev/null +++ b/app/root/etc/nginx/conf.d/default.conf @@ -0,0 +1,18 @@ +server { + listen 80; + listen [::]:80; + + server_name _; + root /directus; + + location / { + try_files $uri $uri/ /index.html =404; + } + + location = /index.html { + rewrite ^ / break; + try_files /index.html =404; + } + + include general.conf; +} diff --git a/app/root/etc/nginx/general.conf b/app/root/etc/nginx/general.conf new file mode 100644 index 0000000..f629984 --- /dev/null +++ b/app/root/etc/nginx/general.conf @@ -0,0 +1,31 @@ +# security headers +add_header X-Frame-Options "SAMEORIGIN" always; +add_header X-XSS-Protection "1; mode=block" always; +add_header X-Content-Type-Options "nosniff" always; +add_header Referrer-Policy "no-referrer-when-downgrade" always; +add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always; + +# . files +location ~ /\.(?!well-known) { + deny all; +} + +# assets, media +location ~* \.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv)$ { + expires 7d; + access_log off; +} + +# svg, fonts +location ~* \.(?:svgz?|ttf|ttc|otf|eot|woff2?)$ { + add_header Access-Control-Allow-Origin "*"; + expires 7d; + access_log off; +} + +# gzip +gzip on; +gzip_vary on; +gzip_proxied any; +gzip_comp_level 6; +gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss application/atom+xml image/svg+xml; diff --git a/app/root/etc/nginx/nginx.conf b/app/root/etc/nginx/nginx.conf new file mode 100644 index 0000000..6984042 --- /dev/null +++ b/app/root/etc/nginx/nginx.conf @@ -0,0 +1,31 @@ +user nginx; +pid /run/nginx.pid; +worker_processes auto; + +events { + multi_accept on; + worker_connections 65535; +} + +http { + charset utf-8; + sendfile on; + tcp_nopush on; + tcp_nodelay on; + server_tokens off; + log_not_found off; + types_hash_max_size 2048; + client_max_body_size 0; + + # MIME + include mime.types; + default_type application/octet-stream; + + # logging + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log warn; + + # load configs + include /etc/nginx/conf.d/*.conf; + include /etc/nginx/sites-enabled/*; +} diff --git a/app/root/etc/services.d/nginx/run b/app/root/etc/services.d/nginx/run new file mode 100644 index 0000000..5e45791 --- /dev/null +++ b/app/root/etc/services.d/nginx/run @@ -0,0 +1,3 @@ +#!/usr/bin/with-contenv sh + +nginx -g "daemon off;" diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..0884b96 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,27 @@ +version: "3" + +services: + app: + image: joshava/directus-app + ports: + - 80:80 + volumes: + - ./app/config.js:/directus/config.js + api: + image: joshava/directus-api + ports: + - 8080:80 + environment: + DATABASE_HOST: mysql + DATABASE_NAME: directus + DATABASE_USERNAME: directus + DATABASE_PASSWORD: directus + ADMIN_EMAIL: "directus@gmail.com" + ADMIN_PASSWORD: "directus" + mysql: + image: mysql:5.7 + environment: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: directus + MYSQL_USER: directus + MYSQL_PASSWORD: directus