├── CSS and SCSS └── vertical-centering.css ├── Drupal ├── 7.x │ ├── add_js_only_for_ie9.md │ ├── commerce_remove_decimal.md │ ├── ctools_modal_centering.md │ ├── generate_first_level_of_menu.md │ ├── get_default_field_image.md │ ├── hook_menu.php │ ├── js_boilerplate_behaviours.js │ ├── js_callback_for_drupal_ajax.md │ ├── panels_remove_system_vars.md │ ├── pathauto_hierarchical_term.md │ ├── print_block_programmatically.md │ ├── print_menu_with_heirarchy.php │ ├── print_views_programmatically.php │ ├── remove_no_content_from_frontpage.md │ ├── rename_or_move_field.md │ ├── russian_plural.md │ └── views_programmatically_add_header.md └── 8.x │ ├── README.md │ ├── disable_cache.md │ ├── drupal-commerce-create-product-variant.md │ ├── drupal-commerce-create-product.md │ ├── drupal_get_title.md │ ├── get_current_route_name.md │ ├── get_route_name_by_path.md │ ├── get_theme_name.md │ ├── print_block_programmatically.md │ └── render_image_style.md ├── ISPManager ├── README.md ├── drupal-cron.md ├── email-tips.md ├── install-composer.md ├── install-drush.md ├── install-nvm.md ├── mariadb-tuning.md ├── nginx │ ├── README.md │ ├── addon-prepare.md │ ├── change-www-docroot.md │ ├── drupal-nginx.md │ ├── nginx-redirect-to-main-domain.md │ └── nginx-tips.md └── php-tips.md ├── JS └── text_color_based_on_background.md ├── LICENSE ├── Linux ├── extract-audio-from-video.md └── list_of_connections.md ├── PHP ├── README.md ├── big_numbers.md ├── convert_multidimensional_array_to_nested_set.md └── russian_plural.md ├── README.md ├── VMs └── docker │ ├── drupal_console_in_dockerizeddrupal.md │ ├── import_mysql_to_container.md │ └── move_docker_container_data.md ├── VestaCP ├── Amazon S3 backups.md ├── CentOS and PHP7.md ├── CentOS install NVM.md ├── Install composer.md ├── drupal-nginx │ ├── README.md │ ├── drupal-project-http-no-www.stpl │ ├── drupal-project-http-no-www.tpl │ ├── drupal-project-https-no-www.stpl │ ├── drupal-project-https-no-www.tpl │ ├── drupal-project.stpl │ ├── drupal-project.tpl │ ├── drupal-ready-http-no-www.stpl │ ├── drupal-ready-http-no-www.tpl │ ├── drupal-ready-https-no-www.stpl │ ├── drupal-ready-https-no-www.tpl │ ├── drupal-ready.stpl │ ├── drupal-ready.tpl │ └── drupal.inc ├── drush-wrapper-for-composer.md └── php-fpm.conf.md ├── centminmod └── installation.md └── docker-based-vps ├── Projects ├── README.md ├── docker-compose.yml ├── example-1.com │ └── docker-compose.yml ├── example-2.com │ ├── .env │ ├── docker-compose.yml │ └── www │ │ └── index.html ├── example-3.com │ ├── .env │ ├── docker-compose.yml │ └── www │ │ └── index.php ├── example-4.com │ ├── .env │ ├── database │ │ └── .gitkeep │ ├── docker-compose.yml │ └── www │ │ └── .gitkeep ├── example-5.com │ ├── .env │ ├── README.md │ ├── database │ │ └── .gitkeep │ ├── docker-compose.yml │ ├── ssh │ │ └── .gitkeep │ └── www │ │ └── .gitkeep └── traefik.yml └── README.md /CSS and SCSS/vertical-centering.css: -------------------------------------------------------------------------------- 1 | .vertical-center { 2 | position: absolute; 3 | top: 50%; 4 | transform: translateY(-50%); 5 | } 6 | -------------------------------------------------------------------------------- /Drupal/7.x/add_js_only_for_ie9.md: -------------------------------------------------------------------------------- 1 | # Adding JavaScript code only for InternetExplorer 9 2 | 3 | ~~~php 4 | // Attach script only of IE 9. 5 | $ie_script = array( 6 | '#browsers' => array('IE' => 'lt IE 9', '!IE' => FALSE), 7 | '#tag' => 'script', 8 | '#attributes' => array( 9 | 'type' => "text/javascript", 10 | ), 11 | '#value' => '$(document).ready(function () { console.log('This is IE9'); });', 12 | '#pre_render' => array('drupal_pre_render_conditional_comments'), 13 | '#weight' => 999, 14 | ); 15 | drupal_add_html_head($ie_script, 'bottom_subscribe_form_placeholder'); 16 | ~~~ 17 | -------------------------------------------------------------------------------- /Drupal/7.x/commerce_remove_decimal.md: -------------------------------------------------------------------------------- 1 | # Drupal Commerce - how to hide decimals in price 2 | 3 | F.e. you have 12 345,00 руб, after this, you will have 12 345 руб. This method is not require to update prices on site, not used in calculating, if decimals exist, they will go to order total, this is just visual fix. 4 | 5 | ~~~php 6 | /** 7 | * hook_commerce_currency_info_alter 8 | */ 9 | function MODULENAME_commerce_currency_info_alter(&$currencies){ 10 | // Don't forget to change RUB to your currency in ISO 4217 format as 11 | // drupal commerce do it. https://ru.wikipedia.org/wiki/ISO_4217 12 | $currencies['RUB']['format_callback'] = 'MODULENAME_commerce_currency_format'; 13 | } 14 | 15 | /** 16 | * Currency format callback 17 | */ 18 | function MODULENAME_commerce_currency_format($amount, $currency, $object = NULL, $convert = TRUE) { 19 | $price = number_format(commerce_currency_round(abs($amount), $currency), 0, $currency['decimal_separator'], $currency['thousands_separator']); 20 | 21 | $replacements = array( 22 | '@code_before' => $currency['code_placement'] == 'before' ? $currency['code'] : '', 23 | '@symbol_before' => $currency['symbol_placement'] == 'before' ? $currency['symbol'] : '', 24 | '@price' => $price, 25 | '@symbol_after' => $currency['symbol_placement'] == 'after' ? $currency['symbol'] : '', 26 | '@code_after' => $currency['code_placement'] == 'after' ? $currency['code'] : '', 27 | '@negative' => $amount < 0 ? '-' : '', 28 | '@symbol_spacer' => $currency['symbol_spacer'], 29 | '@code_spacer' => $currency['code_spacer'], 30 | ); 31 | 32 | return trim(t('@code_before@code_spacer@negative@symbol_before@price@symbol_spacer@symbol_after@code_spacer@code_after', $replacements)); 33 | } 34 | ~~~ 35 | -------------------------------------------------------------------------------- /Drupal/7.x/ctools_modal_centering.md: -------------------------------------------------------------------------------- 1 | # CTools modal centering. 2 | 3 | ~~~javascript 4 | Drupal.behaviors.ctools_modal_fix_centering = { 5 | attach: function (context, settings) { 6 | var $modal = $('#modalContent'); 7 | 8 | function centering() { 9 | var modal_width = $modal.width(), 10 | modal_height = $modal.height(), 11 | win_width = $(window).width(), 12 | win_height = $(window).height(), 13 | pos_left = parseInt(win_width / 2 - modal_width / 2), 14 | pos_top = parseInt(win_height / 2 - modal_height / 2); 15 | 16 | $modal.css({ 17 | 'left': pos_left, 18 | 'top': pos_top < 0 ? 0 : pos_top 19 | }); 20 | if (win_height < modal_height) { 21 | $modal.css({'position': 'absolute'}); 22 | } 23 | else { 24 | $modal.css({'position': 'fixed'}); 25 | } 26 | } 27 | 28 | centering(); 29 | $(window).resize(function () { 30 | centering(); 31 | }); 32 | $modal.resize(function () { 33 | centering(); 34 | }); 35 | } 36 | }; 37 | ~~~ 38 | -------------------------------------------------------------------------------- /Drupal/7.x/generate_first_level_of_menu.md: -------------------------------------------------------------------------------- 1 | # Generate first-level menu 2 | 3 | This code generates only the first menu level. Conveniently, for example for output to a footer. 4 | 5 | ```php 6 | $tree = menu_tree_page_data('main-menu', 1); 7 | $menu_data = menu_tree_output($tree); 8 | ``` 9 | 10 | 11 | ### Example 12 | 13 | template.php file of theme. 14 | 15 | ```php 16 | /** 17 | * Implements hook_preprocess_region().2 18 | * @param $variables 19 | */ 20 | function THEMENAME_preprocess_region(&$variables) { 21 | if ($variables['elements']['#region'] == 'footer') { 22 | $tree = menu_tree_page_data('main-menu', 1); 23 | $menu_data = menu_tree_output($tree); 24 | // Add $menu variable to our region template. 25 | $variables['menu'] = drupal_render($menu_data); 26 | } 27 | } 28 | 29 | ``` 30 | 31 | region--footer.tpl.php 32 | 33 | ```php 34 | 40 | 41 | 47 | 48 | 49 | ``` 50 | 51 | Result 52 | 53 | ![Result](http://i.imgur.com/VkGjIYA.png) 54 | -------------------------------------------------------------------------------- /Drupal/7.x/get_default_field_image.md: -------------------------------------------------------------------------------- 1 | # Getting default image for image field. 2 | 3 | ~~~php 4 | $info = field_info_instance('ENTITY_TYPE', 'FIELD_NAME', 'BUNDLE'); 5 | if (!empty($info) && $info['settings']['default_image'] > 0) { 6 | $default_fid = $info['settings']['default_image']; 7 | $default_file = file_load($default_fid); 8 | // $default_file->uri 9 | } 10 | ~~~ 11 | 12 | -------------------------------------------------------------------------------- /Drupal/7.x/hook_menu.php: -------------------------------------------------------------------------------- 1 | 'TITLE', 15 | 'weight' => 0, 16 | 'page callback' => 'system_admin_menu_block_page', 17 | 'access arguments' => array('access administration pages'), 18 | 'file' => 'system.admin.inc', 19 | 'file path' => drupal_get_path('module', 'system'), 20 | 'position' => 'right', // or left 21 | ); 22 | 23 | return $items; 24 | } 25 | 26 | /** 27 | * @example #2 28 | * Implements hook_menu(). 29 | * This example adds menu group in toolbar (admin_menu). 30 | */ 31 | function MYMODULE_menu() { 32 | $items['admin/NAME'] = array( 33 | 'title' => 'TITLE', 34 | 'weight' => 0, // Greater moves to right, lower to the left. 35 | 'page callback' => 'system_admin_menu_block_page', 36 | 'access arguments' => array('access administration pages'), 37 | 'file' => 'system.admin.inc', 38 | 'file path' => drupal_get_path('module', 'system'), 39 | 'position' => 'right', 40 | ); 41 | 42 | return $items; 43 | } 44 | -------------------------------------------------------------------------------- /Drupal/7.x/js_boilerplate_behaviours.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * JS Boilerplate for Drupal 7. 4 | * Just copy, paste and start coding. 5 | */ 6 | "use strict"; 7 | (function ($, Drupal, window, document, undefined) { 8 | 9 | Drupal.behaviors.MODULE_OR_THEME_NAME = { 10 | attach: function (context, settings) { 11 | // Code here. 12 | } 13 | }; 14 | 15 | })(jQuery, Drupal, this, this.document); 16 | 17 | -------------------------------------------------------------------------------- /Drupal/7.x/js_callback_for_drupal_ajax.md: -------------------------------------------------------------------------------- 1 | # Callback after Drupal AJAX complete. 2 | 3 | ~~~js 4 | /** 5 | * @file 6 | * Action page actions. 7 | */ 8 | "use strict"; 9 | (function ($, Drupal, window, document, undefined) { 10 | 11 | Drupal.behaviors.NAME = { 12 | attach: function (context, settings) { 13 | // Save original. 14 | var ajaxSuccess = Drupal.ajax.prototype.success; 15 | // Rewrite original by own. 16 | Drupal.ajax.prototype.success = function(response, status) { 17 | // Call original callback before own code. 18 | ajaxSuccess.call(response, status); 19 | // Your code after AJAX complete. 20 | } 21 | } 22 | }; 23 | 24 | })(jQuery, Drupal, this, this.document); 25 | ~~~ 26 | -------------------------------------------------------------------------------- /Drupal/7.x/panels_remove_system_vars.md: -------------------------------------------------------------------------------- 1 | # Remove system page title, breadcrumbs and tabs for feature Panels use. 2 | 3 | Sometimes you want to present full page via panels with all elements like page title, breadcrumbs and tabs for users. But they will duplicate with original from page.tpl.php, if you need them on some page, and do not want to create template file for each page where it's needed, there is easy way to do it. 4 | 5 | This code can be written in module and template.php file. 6 | 7 | ~~~php 8 | /** 9 | * Implements hook_preprocess_page(). 10 | */ 11 | function THEMENAME_preprocess_page(&$variables) { 12 | if ($page_display = panels_get_current_page_display()) { 13 | switch ($page_display->uuid) { 14 | // Your UUID will be different, print them to discover them. 15 | case 'ab7fbeba-0503-4857-bfab-23f2a29bc383': // Catalog page 16 | case 'c5086b45-a761-4e10-b68f-fbdbfebf58e1': // Frontpage 17 | // Your variables may be different correspond to base theme. 18 | $variables['breadcrumb'] = FALSE; 19 | $variables['tabs'] = FALSE; 20 | $variables['title'] = FALSE; 21 | } 22 | } 23 | } 24 | ~~~ 25 | 26 | Don't forget in your page.tpl.php wrap this variables with condition. F.e. 27 | 28 | ~~~php 29 | 30 | 31 | 32 | 33 | 34 |

35 | 36 | 37 | 38 | 39 | 40 | ~~~ 41 | -------------------------------------------------------------------------------- /Drupal/7.x/pathauto_hierarchical_term.md: -------------------------------------------------------------------------------- 1 | # Hierarchical path for term and node using pathauto 2 | 3 | For term 4 | 5 | ~~~ 6 | [term:parents:join:/]/[term:name] 7 | ~~~ 8 | 9 | For node 10 | 11 | ~~~ 12 | [node:field-name:parents:join:/]/[node:field-name:name]/[node:title] 13 | ~~~ -------------------------------------------------------------------------------- /Drupal/7.x/print_block_programmatically.md: -------------------------------------------------------------------------------- 1 | 2 | Printing content. 3 | ```php 4 | // Printing only content of the block. 5 | $block = module_invoke('module_name', 'block_view', 'block_delta'); 6 | print $block['content']; 7 | // print $block['subject']; - title 8 | ``` 9 | 10 | Printing full block with contextual links. 11 | 12 | ```php 13 | $block = block_load('MODULE_NAME', 'BLOCK_DELTA'); 14 | $renderable_array = _block_get_renderable_array(_block_render_blocks(array($block))); 15 | print drupal_render($renderable_array); 16 | ``` 17 | -------------------------------------------------------------------------------- /Drupal/7.x/print_menu_with_heirarchy.php: -------------------------------------------------------------------------------- 1 | set_display('display_name'); 18 | $output = $view->preview(); 19 | // If view has result. 20 | if ($view->result) { 21 | return $output; 22 | } 23 | -------------------------------------------------------------------------------- /Drupal/7.x/remove_no_content_from_frontpage.md: -------------------------------------------------------------------------------- 1 | # Remove 'No content for frontpage' and title from frontpage 2 | 3 | 4 | ~~~php 5 | /** 6 | * Implements hook_preprocess_page(). 7 | */ 8 | function THEMENAME_preprocess_page(&$variables) { 9 | if (drupal_is_front_page()) { 10 | // Remove default message. 11 | unset($variables['page']['content']['system_main']['default_message']); 12 | // If you want to remove blocks from frontpage. F.e. for Context, 13 | // uncomment this line and delete upper. 14 | // unset($variables['page']['content']['system_main']); 15 | // Remove title. 16 | drupal_set_title(''); 17 | } 18 | } 19 | ~~~ 20 | -------------------------------------------------------------------------------- /Drupal/7.x/rename_or_move_field.md: -------------------------------------------------------------------------------- 1 | This is example of how to move or rename Drupal 7 field. 2 | 3 | For example we need rename `field_image` to `field_photo`. 4 | 5 | ## Make backup 6 | 7 | Just do it, srsly. 8 | 9 | ## Drush clone 10 | 11 | ``` 12 | drush field-clone field_image field_photo 13 | ``` 14 | 15 | ## Move data from another 16 | 17 | ``` 18 | INSERT field_data_field_photo SELECT * FROM field_data_field_image; 19 | INSERT field_revision_field_photo SELECT * FROM field_revision_field_image; 20 | ``` 21 | 22 | ## Test it 23 | 24 | Test it, and if it's o'kay, just remove old field. -------------------------------------------------------------------------------- /Drupal/7.x/russian_plural.md: -------------------------------------------------------------------------------- 1 | # Russian plural 2 | 3 | ```php 4 | format_plural($count, '@count photo', '@count photos'); 5 | ``` 6 | 7 | Then you must translate this values in administrative interface. 8 | 9 | * @count photo — @count фотография 10 | * @count photos — @count фотографии 11 | * @count[2] photos — @count[2] фотографий 12 | -------------------------------------------------------------------------------- /Drupal/7.x/views_programmatically_add_header.md: -------------------------------------------------------------------------------- 1 | # Programmatically adding field in header\footer of views. 2 | 3 | ~~~php 4 | /** 5 | * Implements hook_views_pre_view(). 6 | */ 7 | function HOOK_views_pre_view(&$view, &$display_id, &$args) { 8 | if ($view->name == 'VIEW_NAME' && $display_id == 'DISPLAY_ID_NAME') { 9 | // Add to header. 10 | // 'header1' must be unique for each item. 11 | $view->add_item($display_id, 'header', 'views', 'header1', array( 12 | 'content' => 'Header content', 13 | 'format' => 'full_html' 14 | )); 15 | // Add to footer 16 | $view->add_item($display_id, 'footer', 'views', 'footer1', array( 17 | 'content' => 'Footer content', 18 | 'format' => 'full_html' 19 | )); 20 | } 21 | } 22 | ~~~ -------------------------------------------------------------------------------- /Drupal/8.x/README.md: -------------------------------------------------------------------------------- 1 | # Drupal 8.x trash folder 2 | 3 | * [**Disable cache**](disable_cache.md) - disable caching for development. 4 | * [**Get route name by path**](get_route_name_by_path.md) 5 | * [**Get current route name**](get_current_route_name.md) 6 | * [**Get theme name**](get_theme_name.md) - examples how to get current active theme. 7 | * [**Print block programmatically**](print_block_programmatically.md) — loading block information for future processing. 8 | * [**Get page title programmatically**](drupal_get_title.md) 9 | * [**Render image styles programmatically**](render_image_style.md) 10 | 11 | ## Drupal Commerce 2 12 | 13 | Drupal Commerce specific code examples. 14 | 15 | * [**Create product variant programmatically**](drupal-commerce-create-product-variant.md) 16 | * [**Create product programmatically**](drupal-commerce-create-product.md) -------------------------------------------------------------------------------- /Drupal/8.x/disable_cache.md: -------------------------------------------------------------------------------- 1 | # Disable caching for development 2 | 3 | # Official way 4 | 5 | At first you must uncomment this lines in `settings.php` file. They at the bottom of file. 6 | 7 | ```php 8 | if (file_exists($app_root . '/' . $site_path . '/settings.local.php')) { 9 | include $app_root . '/' . $site_path . '/settings.local.php'; 10 | } 11 | ``` 12 | 13 | Then you must redirect cache backand to /dev/null 14 | 15 | For this you must copy the file `sites/example.settings.local.php` to `sites/default/settings.local.php`: 16 | 17 | ```sh 18 | sudo cp sites/example.settings.local.php sites/default/settings.local.php 19 | ``` 20 | 21 | In new file `settings.local.php` uncomment two lines: 22 | 23 | ```php 24 | $settings['cache']['bins']['render'] = 'cache.backend.null'; 25 | $settings['cache']['bins']['dynamic_page_cache'] = 'cache.backend.null'; 26 | $settings['cache']['bins']['page'] = 'cache.backend.null'; 27 | ``` 28 | 29 | Then move null backed settings: 30 | 31 | ```sh 32 | sudo cp sites/development.services.yml sites/default/development.services.yml 33 | ``` 34 | 35 | ## Want theming, but twig caches? 36 | 37 | If you don't have `services.yml`: 38 | 39 | ```sh 40 | sudo cp sites/default/default.services.yml sites/default/services.yml 41 | ``` 42 | 43 | Disable it by editing `services.yml` file, by setting change parameters to this: 44 | 45 | ```yaml 46 | parameters: 47 | twig.config: 48 | debug : true 49 | auto_reload: true 50 | cache: false 51 | ``` 52 | 53 | ## Finish him! 54 | 55 | Clear the cache and your done. 56 | 57 | ```sh 58 | drush cr 59 | ``` 60 | 61 | or manualy go to `/core/rebuild.php`. 62 | 63 | ### Example 64 | 65 | An example of development.services.yml. 66 | 67 | ```yaml 68 | # Local development services. 69 | # 70 | # To activate this feature, follow the instructions at the top of the 71 | # 'example.settings.local.php' file, which sits next to this file. 72 | parameters: 73 | http.response.debug_cacheability_headers: true 74 | session.storage.options: 75 | gc_probability: 1, 76 | gc_divisor: 100, 77 | gc_maxlifetime: 200000, 78 | cookie_lifetime: 2000000 79 | twig.config: 80 | debug: true, 81 | auto_reload: true, 82 | cache: true 83 | renderer.config: 84 | required_cache_contexts: ['languages:language_interface', theme, user.permissions] 85 | auto_placeholder_conditions: 86 | max-age: 0 87 | contexts: [session, user] 88 | tags: { } 89 | factory.keyvalue: { } 90 | factory.keyvalue.expirable: { } 91 | filter_protocols: [http, https, ftp, news, nntp, tel, telnet, mailto, irc, ssh, sftp, webcal, rtsp] 92 | cors.config: 93 | enabled: false 94 | allowedHeaders: { } 95 | allowedMethods: { } 96 | allowedOrigins: ['*'] 97 | exposedHeaders: false 98 | maxAge: false 99 | supportsCredentials: false 100 | 101 | services: 102 | cache.backend.null: 103 | class: Drupal\Core\Cache\NullBackendFactory 104 | 105 | ``` 106 | 107 | # Semi-official way 108 | 109 | This is the same thing as described above, but require less operations and can looks a little bit "dirty". But this is the best and fastest way to disable cache on demand. 110 | 111 | At first you must create a file named **services.dev.yml**. You can name it whatever you like, but don't forget to corret that name in PHP code below. Put this file in **/sites/default/services.dev.yml**. 112 | 113 | ### services.dev.yml 114 | 115 | ```yaml 116 | services: 117 | cache.backend.null: 118 | class: Drupal\Core\Cache\NullBackendFactory 119 | parameters: 120 | session.storage.options: 121 | gc_probability: 1 122 | gc_divisor: 100 123 | gc_maxlifetime: 200000 124 | cookie_lifetime: 2000000 125 | twig.config: 126 | debug: true 127 | auto_reload: true 128 | cache: false 129 | renderer.config: 130 | required_cache_contexts: 131 | - url 132 | - route 133 | - languages:language_interface 134 | - theme 135 | - user.permissions 136 | auto_placeholder_conditions: 137 | max-age: 0 138 | contexts: 139 | - session 140 | - user 141 | tags: [ ] 142 | http.response.debug_cacheability_headers: true 143 | factory.keyvalue: [ ] 144 | factory.keyvalue.expirable: [ ] 145 | filter_protocols: 146 | - http 147 | - https 148 | - mailto 149 | - ssh 150 | - sftp 151 | ``` 152 | ## settings.php 153 | 154 | Now you must add some changes to settings.php to enable this service and parameters. To do that, you must add this line to **settings.php**. 155 | 156 | ```php 157 | /** 158 | * Development mode. 159 | */ 160 | if (TRUE) { 161 | assert_options(ASSERT_ACTIVE, TRUE); 162 | \Drupal\Component\Assertion\Handle::register(); 163 | $settings["container_yamls"][] = __DIR__ . "/services.dev.yml"; 164 | $config["system.logging"]["error_level"] = "verbose"; 165 | $config["system.performance"]["css"]["preprocess"] = FALSE; 166 | $config["system.performance"]["js"]["preprocess"] = FALSE; 167 | $settings["cache"]["bins"]["render"] = "cache.backend.null"; 168 | $settings["cache"]["bins"]["dynamic_page_cache"] = "cache.backend.null"; 169 | $settings['cache']['bins']['page'] = 'cache.backend.null'; 170 | $settings["extension_discovery_scan_tests"] = TRUE; 171 | $settings["rebuild_access"] = TRUE; 172 | $settings["skip_permissions_hardening"] = TRUE; 173 | } 174 | ``` 175 | When you need to enable caching and disable all debug tools, you can just change condition statement to `FALSE`. 176 | 177 | I recommend to add this code right after this lines: 178 | 179 | ```php 180 | #if (file_exists($app_root . '/' . $site_path . '/settings.local.php')) { 181 | # include $app_root . '/' . $site_path . '/settings.local.php'; 182 | #} 183 | ``` 184 | 185 | # Using DrupalConsole 186 | 187 | This will be only disable Twig caches, but not disable entire cache which affect code. 188 | 189 | ```bash 190 | drupal site:mode dev 191 | ``` 192 | 193 | Revert back 194 | 195 | ``` 196 | drupal site:mode prod 197 | ``` 198 | -------------------------------------------------------------------------------- /Drupal/8.x/drupal-commerce-create-product-variant.md: -------------------------------------------------------------------------------- 1 | # Drupal Commerce 2 create product programmatically 2 | 3 | ## Example 1 4 | 5 | ```php 6 | $price = new \Drupal\commerce_price\Price('117', 'RUB'); 7 | $variant = ProductVariation::create([ 8 | 'type' => 'led_light', 9 | 'sku' => 'test', 10 | 'status' => 1, 11 | 'price' => $price, 12 | ]); 13 | ``` 14 | -------------------------------------------------------------------------------- /Drupal/8.x/drupal-commerce-create-product.md: -------------------------------------------------------------------------------- 1 | # Drupal Commerce 2 create product programmatically 2 | 3 | -------------------------------------------------------------------------------- /Drupal/8.x/drupal_get_title.md: -------------------------------------------------------------------------------- 1 | # Drupal 8 get page title programmatically. 2 | 3 | 4 | ```php 5 | $request = \Drupal::request(); 6 | $route_match = \Drupal::routeMatch(); 7 | $title = \Drupal::service('title_resolver')->getTitle($request, $route_match->getRouteObject()); 8 | ``` -------------------------------------------------------------------------------- /Drupal/8.x/get_current_route_name.md: -------------------------------------------------------------------------------- 1 | # Get current route name. 2 | 3 | ~~~php 4 | $rout_name = \Drupal::routeMatch()->getRouteName(); 5 | ~~~ 6 | -------------------------------------------------------------------------------- /Drupal/8.x/get_route_name_by_path.md: -------------------------------------------------------------------------------- 1 | # Get route name by path. 2 | 3 | 4 | ~~~php 5 | \Drupal::service('path.validator')->getUrlIfValid('PATH'); 6 | \Drupal::service('path.validator')->getUrlIfValid('node'); 7 | \Drupal::service('path.validator')->getUrlIfValid('node/*'); 8 | ~~~ 9 | -------------------------------------------------------------------------------- /Drupal/8.x/get_theme_name.md: -------------------------------------------------------------------------------- 1 | # Get theme name 2 | 3 | ## Example 1 4 | 5 | This method returns diffirent theme nemes depends on where you are. 6 | F.e. on node page it can show `bartik`, but on admin sections is `seven`. 7 | 8 | So - this code returns current theme for current page. 9 | 10 | ~~~php 11 | $theme = \Drupal::theme()->getActiveTheme()->getName(); 12 | ~~~ 13 | 14 | ## Example 2 15 | 16 | This example returns current active theme selected as default for site. 17 | 18 | ~~~php 19 | $theme = \Drupal::config('system.theme')->get('default'); 20 | ~~~ 21 | -------------------------------------------------------------------------------- /Drupal/8.x/print_block_programmatically.md: -------------------------------------------------------------------------------- 1 | # Print block programmatically 2 | 3 | ## Content blocks 4 | 5 | This block are created via default Drupal core block system. 6 | 7 | Block id is integer value from database. `block_content:dae619eb-d5f5-4804-8534-6b520a4a1815` — this **is not** block id. The fastes way to find block id, is to navigate to `/admin/structure/block/block-content` and look at the URL of needed block. 8 | 9 | ```php 10 | $block = \Drupal\block_content\Entity\BlockContent::load('BLOCK_ID'); 11 | $block_array = \Drupal::entityTypeManager()->getViewBuilder('block_content')->view($block); 12 | ``` 13 | 14 | ## Plugin blocks 15 | 16 | Those kind of block are defined in the modules via Plugin API system. 17 | 18 | ```php 19 | $block_manager = \Drupal::service('plugin.manager.block'); 20 | $block_plugin = $block_manager->createInstance('BLOCK_ID', []); 21 | $block_array = $plugin_block->build(); 22 | ``` 23 | 24 | Some blocks might have require some access or cache information, you can pass them via methods and call directly. 25 | 26 | ```php 27 | $block_access = $plugin_block->access(\Drupal::currentUser()); 28 | $cache_contexts = $plugin_block->getCacheContexts(); 29 | $cache_tags = $plugin_block->getCacheTags(); 30 | ``` -------------------------------------------------------------------------------- /Drupal/8.x/render_image_style.md: -------------------------------------------------------------------------------- 1 | # Render image style programmatically 2 | 3 | ## Via Render API 4 | 5 | ```php 6 | $render = [ 7 | '#theme' => 'image_style', 8 | '#style_name' => 'medium', 9 | '#uri' => 'public://image.jpg', 10 | ]; 11 | ``` 12 | 13 | ## Via entity type manager 14 | 15 | ```php 16 | $style = \Drupal::entityTypeManager()->getStorage('image_style')->load('medium'); 17 | $url = $style->buildUrl('public://image.jpg'); 18 | ``` 19 | -------------------------------------------------------------------------------- /ISPManager/README.md: -------------------------------------------------------------------------------- 1 | # ISPManager 6 Tips & Tricks 2 | 3 | This file contains small instruction how to prepare ISPManager 5 to use it with **Drupal**. 4 | 5 | 6 | ### [NGINX instructions](./nginx/README.md) 7 | 8 | Instructions for NGINX users. 9 | 10 | ### [Composer installation](install-composer.md) 11 | 12 | Instruction for composer installation with support alternative PHP versions. 13 | 14 | ### [Drush installation](install-drush.md) 15 | 16 | Instruction for Drush installation with support alternative PHP versions. 17 | 18 | ### [NVM installation](install-nvm.md) 19 | 20 | If you're using NVM, you might to read this. A little tip to save your time. 21 | 22 | ### [MariaDB tuning](mariadb-tuning.md) 23 | 24 | By default MariaDB not configured for common usage, but can be tuned. 25 | 26 | ### [Drupal cron](drupal-cron.md) 27 | 28 | Several ways to handle Drupal cron. 29 | -------------------------------------------------------------------------------- /ISPManager/drupal-cron.md: -------------------------------------------------------------------------------- 1 | # ISPManager 5: Drupal cron 2 | 3 | You can run cron in multiple ways. This is summary of [this documentation](https://www.drupal.org/docs/7/setting-up-cron/configuring-cron-jobs-using-the-cron-command). 4 | 5 | ## Recommendations 6 | 7 | - Run cron regulary, don't forget to run it at least once per day. 8 | - Don't use **Automated cron** module shipped with Drupal core and installed by default on **Standard** profile. **Uninstall it**. It's reduces performance for random user is very drstically. 9 | - It's better to run cron via CLI, not with HTTP URL, because, often, CLI is faster and has less restrictions, e.g. execution time for CLI often is disabled completely. 10 | 11 | **Best cron approach**: 12 | 13 | 1. `drush cron` or manually `php /path/to/cron.php`. This is **CLI** mode. It's faster and have less restrictions. Didn't touch web-server in any way and didn't affect users. 14 | 2. `wget` or `curl` with cron URL. This is not a bad solution, but better user #1. 15 | 3. Automated Cron — use it only on shared hostings where you can't create cron operation with CLI method. 16 | 17 | ## Before 18 | 19 | - Log in as user with domain which need to be configured to run cron. 20 | - Navigate to Dashboard > Scheduler (cron) 21 | - Add 22 | 23 | ## Drush 24 | 25 | Configure [Drush](install-drush.md) and use it! It's simpliest way. 26 | 27 | `export HOME=PATH_TO_SITE_ROOT; /usr/local/bin/drush cron --quiet --root=$HOME` 28 | 29 | - `PATH_TO_SITE_ROOT` - path to site root. This is essential, because cron doesn't know anything about environment variables, but Drush trying to get `$HOME` in every request. So it's mandatory. E.g. `/var/www/USERNAME/data/DOMAIN_NAME` 30 | - `--quiet` - for not printing any data to cron. If you wan't to send email with cron results, remove it. 31 | 32 | You can use `/usr/local/bin/drush7` or other version you install by instructions to handle multiple Drupal versions and PHP versions. 33 | 34 | ## WGET 35 | 36 | `wget --spider CRON_URL` 37 | -------------------------------------------------------------------------------- /ISPManager/email-tips.md: -------------------------------------------------------------------------------- 1 | # ISPManager 5: Email tips 2 | 3 | This tips can be halpful if you're using DNS server from VPS provider, and not from ISP manager. This can lead to problems, but on many VPS's there is no way to handle it via DNS from ISP. 4 | 5 | ## SPF and DKIM for domain 6 | 7 | This can help avoid spam filters. 8 | 9 | 1. Enable DKIM support: Settings > Features > Mail server > Edit and check OpenDKIM. 10 | 2. Add new mail domain: Domains > Mail domains > Add. Enter domain name and check "Enable DKIM for domain". 11 | 12 | Edit your DNS entries by adding new ones: 13 | 14 | * **SPF** 15 | 16 | - **Subdomain**: your main domain, f.e. `example.com` 17 | - **Type**: `TXT` 18 | - **Value**: `v=spf1 ip4:SERVER_IP ~all` - replace SERVER_IP with IP same as for A record. You you want to use it f.e. with Yandex Mail append `include=_spf.yandex.ru` before `~all`. 19 | - **TTL**: `600`, or leave it by default. This is not so important. 20 | 21 | * **DKIM** 22 | 23 | - **Subdomain**: `mail._domainkey.example.com` - replace example.com with your domain. Must be the same as for DKIM record created before. 24 | - **Type**: `TXT` 25 | - **Value**: `v=DKIM1; k=rsa; p=DKIM_KEY` - you must replace DKIM_KEY with your value. You can find this value only on server. Use shell or SSH for accesing it: `cat /etc/exim/ssl/example.com.txt`. 26 | - **TTL**: `600`, or leave it by default. This is not so important. 27 | 28 | -------------------------------------------------------------------------------- /ISPManager/install-composer.md: -------------------------------------------------------------------------------- 1 | # Composer installation for ISPManager 6 2 | 3 | ```bash 4 | # On root user. 5 | php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" 6 | php composer-setup.php 7 | php -r "unlink('composer-setup.php');" 8 | sudo chmod +x composer.phar 9 | sudo mv composer.phar /usr/local/bin/composer 10 | ``` 11 | 12 | ## Specific PHP version for Composer for specific user 13 | 14 | 1. Log in as that user. 15 | 2. `mkdir ~/bin` 16 | 3. `touch ~/bin/php` 17 | 4. Edit `~/bin/php` and add this content, specifing a required PHP version for binary and configs and changing path with username: 18 | 19 | ```sh 20 | #!/bin/sh 21 | PHP_EXEC="/opt/php81/bin/php -c /var/www/USERNAME/data/php-bin-isp-php81" 22 | $PHP_EXEC "$@" 23 | ``` 24 | 5. `chmod +x ~/bin/php` 25 | 5. Edit or create `~/.bash_profile` 26 | 1. **Create a new one** (default, because file doesn'e exists): `echo "export PATH=$HOME/bin:$PATH" >> ~/.bash_profile` 27 | 7. Update `PATH` with appending `~/bin`. 28 | 29 | ## Specific PHP version for Composer for all users 30 | 31 | E.g., for PHP 8.1. 32 | 33 | 1. `touch /usr/local/bin/composer81`. 34 | 2. Add contents 35 | 36 | ```bash 37 | #!/bin/bash 38 | env PATH="/opt/php81/bin:$PATH" php /usr/local/bin/composer-bin "$@" 39 | ``` 40 | 41 | 3. `chmod +x /usr/local/bin/composer81` 42 | 43 | You can create as many as you want, same files with different PHP version. F.e. `/usr/local/bin/composer56` for PHP 5.6. 44 | -------------------------------------------------------------------------------- /ISPManager/install-drush.md: -------------------------------------------------------------------------------- 1 | # Drush installation for ISPManager 6 2 | 3 | ### Different PHP versions 4 | 5 | E.g, for PHP 8.1. 6 | 7 | 1. `touch /usr/local/bin/drush81`. 8 | 2. Add content: 9 | 10 | ```bash 11 | #!/bin/bash 12 | env PATH="/opt/php81/bin:./vendor/bin:$PATH" drush "$@" 13 | ``` 14 | 15 | 3. `chmod +x /usr/local/bin/drush81` 16 | 17 | You can create as many as you want same files with different php version. F.e. /usr/local/bin/drush56 for PHP 5.6. 18 | 19 | ## Drush 7 for Drupal 7 20 | 21 | _This can be used for multiple drush version on one server._ 22 | 23 | You might be needing Drush 7.x for older sites. This is also possible, but better to create new command for it. 24 | 25 | 1. `cd /usr/local/src` 26 | 2. `git clone https://github.com/drush-ops/drush.git drush7` 27 | 3. `cd drush7` 28 | 4. `git checkout 7.4.0` or whatever [version](https://github.com/drush-ops/drush/tags) you want. 29 | 5. `ln -s /usr/local/src/drush7/drush /usr/local/bin/drush7` 30 | 6. `composer install` (must be installed) 31 | 7. `drush7 --version` 32 | -------------------------------------------------------------------------------- /ISPManager/install-nvm.md: -------------------------------------------------------------------------------- 1 | # Install NVM on ISPManager 5 2 | 3 | 1. Login via ssh form user which needs NVM. 4 | 2. `touch ~/.bash_profile` if not exist. 5 | 3. [Install as usuall](https://github.com/creationix/nvm). -------------------------------------------------------------------------------- /ISPManager/mariadb-tuning.md: -------------------------------------------------------------------------------- 1 | # MariaDB tuning in ISPManager 6 2 | 3 | Settings > Database 4 | 5 | ## Common improvements 6 | 7 | ### max-allowed-packet 8 | 9 | Set it to `256M` (268435456). 10 | 11 | Default to `10M` is cause "ERROR 2006 (HY000) at line 1977: MySQL server has gone away" error. You won't be able to import big database. Also this error can be get using Batch or Queue API with a big context data. 12 | 13 | ### query-cache-limit and query-cache-size 14 | 15 | Set it to `1M` (1048576, default) and `10M` (10485760). 16 | 17 | ### innodb-flush-log-at-trx-commit 18 | 19 | By default is set to `1` - and this is most safety choice. 20 | 21 | But when set to `2` you can expect better performance ([~x75-150](https://dba.stackexchange.com/a/56673) times faster for write operations) 22 | 23 | Change it on your own choice, and before change, read [this](https://dba.stackexchange.com/questions/12611/is-it-safe-to-use-innodb-flush-log-at-trx-commit-2). 24 | -------------------------------------------------------------------------------- /ISPManager/nginx/README.md: -------------------------------------------------------------------------------- 1 | # ISPManager 6 NGINX instructions 2 | 3 | ### [Addon: Drupal NGINX](drupal-nginx.md) 4 | 5 | Instruction how to configure NGINX configs to work with Drupal 7 and 8. This is for FastCGI (nginx + php-fpm) variation. 6 | 7 | ### [NGINX tips](nginx-tips.md) 8 | 9 | Some tips for NGINX which can improve your life with ISP. 10 | 11 | ### [Addon: Redirect to main domain](nginx-redirect-to-main-domain.md) 12 | 13 | Instruction how to redirect to main domain from aliases. 14 | 15 | ### [Change WWW-domain docroot](change-www-docroot.md) 16 | 17 | This might be helpful if you want to migrate to Composer Drupal Project or vice versa. 18 | -------------------------------------------------------------------------------- /ISPManager/nginx/addon-prepare.md: -------------------------------------------------------------------------------- 1 | # ISPManager 5: Preparation before NGINX addon creation 2 | 3 | This instruction is needs to be done before any addon from other instructions will be created. 4 | 5 | Do it only once, because copying can broke files. 6 | 7 | 1. `cd /usr/local/mgr5/etc/templates` 8 | 2. Copy default templates to working directory. 9 | 10 | ```bash 11 | cp default/nginx-vhosts.template ./nginx-vhosts.template 12 | cp default/nginx-vhosts-ssl.template ./nginx-vhosts-ssl.template 13 | ``` 14 | 15 | 3. Open **nginx-vhosts.template** and change line with SSL at the end from 16 | 17 | `{% import etc/templates/default/nginx-vhosts-ssl.template %}` 18 | 19 | to 20 | 21 | `{% import etc/templates/nginx-vhosts-ssl.template %}` 22 | 23 | -------------------------------------------------------------------------------- /ISPManager/nginx/change-www-docroot.md: -------------------------------------------------------------------------------- 1 | # Change WWW docroot 2 | 3 | ISPManager only allows to set docroot when you create new www-domain, but then, not allows to change it via UI. 4 | 5 | There are three ways. 6 | 7 | 1. Delet domain and add again, but this method will erase all your data. It's not acceptable for production sites. 8 | 2. Change this value in ISP Database. 9 | 10 | ```bash 11 | sqlite3 /usr/local/mgr5/etc/ispmgr.db 12 | ``` 13 | 14 | Looking for domain id: 15 | 16 | ```sql 17 | select * from webdomain; 18 | ``` 19 | 20 | Update location. Don't forget to change $USERNAME$, $DOMAIN$, $DOMAIN_ID$ on your values. 21 | 22 | ```sql 23 | update webdomain set docroot="/var/www/$USERNAME$/data/www/$DOMAIN_ID$/web" where id=1 24 | ``` 25 | 26 | Press `Ctrl + D` to exit. 27 | 28 | 3. Delete WWW-domain, but not check for removing data. Recreate WWW-domain with new values. -------------------------------------------------------------------------------- /ISPManager/nginx/drupal-nginx.md: -------------------------------------------------------------------------------- 1 | # ISPManager 6 — Drupal NGINX integration instructions 2 | 3 | 1. Make sure you complete [addon preparation insutrction](addon-prepare.md). 4 | 2. `cd /usr/local/mgr5/etc/xml` 5 | 3. `touch ispmgr_mod_drupal_nginx.xml` (prefix `ispmgr_mod_` is required) 6 | 4. Put this content into it. 7 | 8 | ```xml 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 | 33 | 34 | 35 | Drupal NGINX 36 | Отметьте, чтобы конфигурации NGINX были оптимизированы под Drupal. 37 | 38 | 39 | Drupal NGINX 40 | Отметьте, чтобы конфигурации NGINX были оптимизированы под Drupal. 41 | 42 | 43 | 44 | 45 | 46 | Drupal NGINX 47 | Check for optimized Drupal NGINX config. 48 | 49 | 50 | Drupal NGINX 51 | Check for optimized Drupal NGINX config. 52 | 53 | 54 |
55 | ``` 56 | 57 | 5. `cd /usr/local/mgr5/etc/templates` 58 | 6. `touch nginx-drupal.template` 59 | 7. Put this into `nginx-drupal.template` 60 | 61 | ```nginx 62 | # Uncomment it to handle 404 with Drupal. This is not recommended for peroformance 63 | # but if you want beautiful 404 pages with full control. That's your choise. 64 | #error_page 404 /index.php; 65 | 66 | # Buffers definition. allows of up to 260k to be passed in memory. 67 | client_body_buffer_size 1m; 68 | proxy_buffering on; 69 | proxy_buffer_size 4k; 70 | proxy_buffers 8 32k; 71 | 72 | # Hide default Drupal headers. Worthless payload for production. 73 | fastcgi_hide_header 'X-Drupal-Cache'; 74 | fastcgi_hide_header 'X-Generator'; 75 | fastcgi_hide_header 'X-Drupal-Dynamic-Cache'; 76 | 77 | location / { 78 | # Private files shouldn't be accessible from outside. 79 | location ~* /sites/.+/files/private/ { 80 | internal; 81 | } 82 | 83 | # Image styles should be processed by Drupal, not as static files. 84 | # Also it supports Drupal 10.1+ new JS/CSS aggregation system. 85 | location ~* /files/(css|js|styles)/ { 86 | access_log off; 87 | expires 1y; 88 | try_files $uri @drupal; 89 | } 90 | 91 | location ~* /sites/.+/files/.+\.txt { 92 | access_log off; 93 | expires 1y; 94 | tcp_nodelay off; 95 | open_file_cache max=1000 inactive=30s; 96 | open_file_cache_valid 30s; 97 | open_file_cache_min_uses 2; 98 | open_file_cache_errors off; 99 | } 100 | 101 | # drupal/advagg 102 | location ~* /sites/.+/files/advagg_css/ { 103 | expires max; 104 | add_header ETag ''; 105 | add_header Last-Modified 'Wed, 20 Jan 1988 04:20:42 GMT'; 106 | add_header Accept-Ranges ''; 107 | location ~* /sites/.*/files/advagg_css/.+\.css$ { 108 | access_log off; 109 | add_header Cache-Control "public, max-age=31536000, no-transform, immutable"; 110 | try_files $uri @drupal; 111 | } 112 | } 113 | 114 | # drupal/advagg 115 | location ~* /sites/.+/files/advagg_js/ { 116 | expires max; 117 | add_header ETag ''; 118 | add_header Last-Modified 'Wed, 20 Jan 1988 04:20:42 GMT'; 119 | add_header Accept-Ranges ''; 120 | location ~* /sites/.*/files/advagg_js/.+\.js$ { 121 | access_log off; 122 | add_header Cache-Control "public, max-age=31536000, no-transform, immutable"; 123 | try_files $uri @drupal; 124 | } 125 | } 126 | 127 | # drupal/hacked 128 | location ~* /admin/reports/hacked/.+/diff/ { 129 | try_files $uri @drupal; 130 | } 131 | 132 | # Allow dynamic XML endpoints. You need that if you have routes with '.xml' ending. 133 | #location ~* ^.+\.xml { 134 | # try_files $uri @drupal; 135 | #} 136 | 137 | # Force 'sitemap.xml' to be processed by Drupal, this is not a static file for 99.99%. 138 | location ~* /sitemap.xml { 139 | try_files $uri @drupal; 140 | } 141 | 142 | # Do not allow to dowonload any config. 143 | location ^~ /sites/.+/files/config_.*/ { 144 | internal; 145 | } 146 | 147 | # Don't allow direct access to PHP files in the vendor directory. 148 | location ~ ^/vendor/ { 149 | internal; 150 | } 151 | 152 | # Handle private files through Drupal. 153 | location ~ ^/system/files/ { 154 | try_files $uri @drupal; 155 | } 156 | 157 | # Replica of regex from Drupals core .htaccess. 158 | location ~* \.(engine|txt|inc|install|make|module|profile|po|sh|.*sql|theme|twig|tpl(\.php)?|xtmpl|yml)(~|\.sw[op]|\.bak|\.orig|\.save)?$|^(\.(?!well-known).*|Entries.*|Repository|Root|Tag|Template|composer\.(json|lock)|(package|package-lock)\.json|yarn\.lock|web\.config)$\.php(~|\.sw[op]|\.bak|\.orig|\.save)$ { 159 | return 404; 160 | } 161 | 162 | # Static files. 163 | location ~* ^.+\.(?:css|cur|js|jpe?g|gif|htc|ico|png|xml|otf|ttf|eot|woff|woff2|svg|mp4|svgz|ogg|ogv|pdf|pptx?|zip|tgz|gz|rar|bz2|doc|xls|exe|tar|mid|midi|wav|bmp|rtf|txt|map|webp)$ { 164 | access_log off; 165 | tcp_nodelay off; 166 | expires 1y; 167 | 168 | add_header Pragma "cache"; 169 | add_header Cache-Control "public"; 170 | 171 | open_file_cache max=1000 inactive=30s; 172 | open_file_cache_valid 30s; 173 | open_file_cache_min_uses 2; 174 | open_file_cache_errors off; 175 | } 176 | 177 | try_files $uri @drupal; 178 | } 179 | 180 | # This rewrites pages to be sent to PHP processing 181 | location @drupal { 182 | rewrite ^/(.*)$ /index.php; 183 | } 184 | 185 | location = /favicon.ico { 186 | log_not_found off; 187 | access_log off; 188 | access_log off; 189 | expires max; 190 | } 191 | 192 | # With robotstxt module support. 193 | location = /robots.txt { 194 | allow all; 195 | log_not_found off; 196 | access_log off; 197 | try_files $uri @drupal; 198 | } 199 | 200 | location = /humans.txt { 201 | allow all; 202 | log_not_found off; 203 | access_log off; 204 | try_files $uri @drupal; 205 | } 206 | 207 | # XML Dynamic support 208 | location ~* \.xml { 209 | try_files $uri @drupal; 210 | } 211 | 212 | # Disallow access to .bzr, .git, .hg, .svn, .cvs directories: return 213 | # 404 as not to disclose information. 214 | location ^~ /.bzr { 215 | return 404; 216 | } 217 | 218 | location ^~ /.git { 219 | return 404; 220 | } 221 | 222 | location ^~ /.hg { 223 | return 404; 224 | } 225 | 226 | location ^~ /.svn { 227 | return 404; 228 | } 229 | 230 | location ^~ /.cvs { 231 | return 404; 232 | } 233 | 234 | # Disallow access to patches directory. 235 | location ^~ /patches { 236 | return 404; 237 | } 238 | 239 | # Any other attempt to access PHP files returns a 404. 240 | location ~* ^.+\.php$ { 241 | return 404; 242 | } 243 | 244 | ``` 245 | 246 | 8. `cp nginx-drupal.template nginx-drupal-ssl.template` because otherwise ISP thinks he going into recurrsion when used twice. 247 | 9. Edit `nginx-vhosts.template`. Add content below before `location /` in **both files** but in `server {}` block. 248 | 249 | ```nginx 250 | {% if $DRUPAL_NGINX == on %} 251 | {% import etc/templates/nginx-drupal.template %} 252 | {% endif %} 253 | ``` 254 | 10. Edit `nginx-vhosts-ssl.template`. Add content below before `location /` in **both files** but in `server {}` block. 255 | 256 | ```nginx 257 | {% if $DRUPAL_NGINX == on %} 258 | {% import etc/templates/nginx-drupal-ssl.template %} 259 | {% endif %} 260 | ``` 261 | 262 | 11. `mkdir /usr/local/mgr5/etc/sql/webdomain.addon` (if not exist) 263 | 12. `cd /usr/local/mgr5/etc/sql/webdomain.addon` 264 | 13. `touch drupal_nginx` 265 | 14. Edit **drupal_nginx** and add this lines: 266 | 267 | ```conf 268 | default=off 269 | ``` 270 | 271 | 15. `/usr/local/mgr5/sbin/mgrctl -m ispmgr exit` 272 | 16. Kill DB cache `rm -rf /usr/local/mgr5/var/.db.cache*` 273 | 17. Restart core `killall core` 274 | 275 | 276 | Now, visit WWW-domain, on edit form will be new checkbox. Check it and save to apply NGINX configs for Drupal. 277 | 278 | ![Setting](https://i.imgur.com/w1MT0Fr.png) 279 | -------------------------------------------------------------------------------- /ISPManager/nginx/nginx-redirect-to-main-domain.md: -------------------------------------------------------------------------------- 1 | # ISPManager 5 — Redirect to main domain 2 | 3 | This addon adds possibility to redirect all requests from aliases to main domain. 4 | 5 | 1. Make sure you complete [addon preparation insutrction](addon-prepare.md). 6 | 2. `cd /usr/local/mgr5/etc/xml` 7 | 3. `touch ispmgr_mod_redirect_to_main.xml` 8 | 4. Put this content into it. 9 | 10 | ```xml 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 |
25 |
26 | 27 | 28 | 29 | Перенаправлять все запросы на основной домен 30 | Отметьте, чтобы все запросы были направлены на основной домен, включая WWW-перенаправление. 31 | 32 | 33 | 34 | 35 | 36 | Redirect all request to main domain 37 | Check for redirect all requests to main domain including WWW-domain. 38 | 39 | 40 |
41 | ``` 42 | 43 | 5. `cd /usr/local/mgr5/addon` 44 | 6. `touch redirect_to_main` 45 | 7. Put this content into it. 46 | 47 | ```bash 48 | #!/bin/bash 49 | 50 | if [[ "$PARAM_redirect_to_main" = "on" ]] 51 | then 52 | cat | sed 's|$|on|' 53 | else 54 | cat | sed 's|$|off|' 55 | fi 56 | ``` 57 | 58 | 8. `cd /usr/local/mgr5/etc/templates` 59 | 9. Edit **nginx-vhosts.template** and **nginx-vhosts-ssl.template**, add config below before `location /` in **both files** or somwhere below in `server {}` block. 60 | 61 | ```nginx 62 | {% if $REDIRECT_TO_MAIN == on %} 63 | if ($http_host != {% $NAME %}) { 64 | rewrite ^(.*)$ $scheme://{% $NAME %}$1 permanent; 65 | } 66 | {% endif %} 67 | ``` 68 | 69 | 10. `mkdir /usr/local/mgr5/etc/sql/webdomain.addon` (if not exist) 70 | 11. `cd /usr/local/mgr5/etc/sql/webdomain.addon` 71 | 12. `touch redirect_to_main` 72 | 13. Edit **redirect_to_main** and add this lines: 73 | 74 | ```conf 75 | default=off 76 | ``` 77 | 78 | 14. Kill DB cache `rm -rf /usr/local/mgr5/var/.db.cache*` 79 | 15. Restart core `killall core` 80 | 81 | Now, visit WWW-domain, on edit form will be new checkbox. 82 | -------------------------------------------------------------------------------- /ISPManager/nginx/nginx-tips.md: -------------------------------------------------------------------------------- 1 | # NGINX tips 2 | 3 | ## Improve gzip mimes 4 | 5 | If you are using gzip on site, the ISP is provide very common mime types to handle with gzip. It can be broader. 6 | 7 | 1. Open `/usr/local/mgr5/etc/ispmgr.conf`. 8 | 2. Add 9 | 10 | ``` 11 | path nginx-gzip-types text/css text/javascript text/xml text/plain text/x-component application/javascript application/x-javascript application/json application/xml application/rss+xml application/atom+xml font/ttf font/opentype font/woff font/woff2 application/vnd.ms-fontobject image/svg+xml 12 | ``` 13 | 14 | You can edit by your needs. It will apply to all configs. If you want it only for specific website, edit config directly. 15 | 16 | ## Improve MIME types assotiation 17 | 18 | ISP is not provides mime types for fonts at all, which results to response for them with octet-stream type. Which is not a good idea. It will lead to miss gzip and other possible slowdowns. 19 | 20 | 1. Open `/etc/nginx/mime.types` 21 | 2. Add 22 | 23 | ``` 24 | font/ttf ttf; 25 | font/opentype otf; 26 | font/woff woff; 27 | font/woff2 woff2; 28 | application/vnd.ms-fontobject eot; 29 | ``` 30 | -------------------------------------------------------------------------------- /ISPManager/php-tips.md: -------------------------------------------------------------------------------- 1 | # ISPManager 5: PHP tips 2 | 3 | This tips mainly for Drupal sites. 4 | 5 | ## After installation new PHP version 6 | 7 | Enable PHP extensions: 8 | 9 | - xmlreader 10 | - xmlwriter 11 | - opcache 12 | - bcmath (required by drupal/commerce) 13 | 14 | ### max_execution_time 15 | 16 | Set it at least for `60`. `30` by default is to low for some heavy operations. I using `600`. 17 | 18 | ### post_max_size 19 | 20 | `128M` or whatever you want. 21 | 22 | ### upload_max_filesize 23 | 24 | `128M` or whatever you want. Can't be more than `upload_max_filesize`. 25 | 26 | ### opcache.revalidate_freq 27 | 28 | `0` 29 | 30 | ### opcache.file_update_protection 31 | 32 | `10` 33 | 34 | ### opcache.enable_cli 35 | 36 | `1` or `On` 37 | 38 | -------------------------------------------------------------------------------- /JS/text_color_based_on_background.md: -------------------------------------------------------------------------------- 1 | # Determinate what color for text better use, black or white based on background color. 2 | 3 | ~~~js 4 | var textColor = function (bgColor) { 5 | var r = bgColor.r * 255, 6 | g = bgColor.g * 255, 7 | b = bgColor.b * 255; 8 | var yiq = (r * 299 + g * 587 + b * 114) / 1000; 9 | return (yiq >= 128) ? 'black' : 'white'; 10 | } 11 | ~~~ 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2004 Sam Hocevar 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | -------------------------------------------------------------------------------- /Linux/extract-audio-from-video.md: -------------------------------------------------------------------------------- 1 | 1. Find out the audio sources using command: `ffmpeg -i FILENAME` 2 | 2. Export needed sound `ffmpeg -i FILENAME -c:a libmp3lame -q:a 4 output.mp3` 3 | 2.1 To specify audio stream line you must use `-map 0:LINE_NUMBER`. 4 | 5 | `-q:a` is quality. More info [here](https://trac.ffmpeg.org/wiki/Encode/MP3). 4 is great for all cases. It's equals bitrate 140-185 kbit/s. -------------------------------------------------------------------------------- /Linux/list_of_connections.md: -------------------------------------------------------------------------------- 1 | Helps to detect DDOSS IP's 2 | 3 | ~~~ 4 | netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n 5 | ~~~ 6 | -------------------------------------------------------------------------------- /PHP/README.md: -------------------------------------------------------------------------------- 1 | # PHP 2 | 3 | [Russian plural](russian_plural.md) 4 | 5 | [Big numbers formatter](big_numbers.md) - convert big numbers, such as 1000000 to 1M, 1000 to 1k, 2500 to 2.5k 6 | 7 | [Convert multidimensional array to nested set](convert_multidimensional_array_to_nested_set.md) -------------------------------------------------------------------------------- /PHP/big_numbers.md: -------------------------------------------------------------------------------- 1 | # Big numbers formatter 2 | 3 | This function makes ease to format big numbers. 4 | 5 | ~~~php 6 | /** 7 | * Shortiner for big numbers. Translate numbers like 1000 to 1k, 1 000 000 to 1M. 8 | */ 9 | function format_big_number($number) { 10 | $tokens = array( 11 | 1000000 => 'M', 12 | 1000 => 'K', 13 | 1 => '' 14 | ); 15 | 16 | foreach ($tokens as $unit => $text) { 17 | if ($number < $unit) { 18 | continue; 19 | } 20 | return floatval(number_format($number / $unit, 1)) . $text; 21 | } 22 | } 23 | ~~~ 24 | 25 | 26 | # Example 27 | ~~~php 28 | echo format_big_number(100); // 100 29 | echo format_big_number(1000); // 1K 30 | echo format_big_number(20500); // 20.5K 31 | echo format_big_number(1500000); // 1.5M 32 | ~~~ 33 | -------------------------------------------------------------------------------- /PHP/convert_multidimensional_array_to_nested_set.md: -------------------------------------------------------------------------------- 1 | # PHP: Convert multidimensional array to nested set array 2 | 3 | [Nested set model on wikipedia.](https://en.wikipedia.org/wiki/Nested_set_model) 4 | 5 | This code sort multidimensional array to new array with nested set, also set left, right and depth keys. 6 | 7 | ![Example](https://upload.wikimedia.org/wikipedia/commons/thumb/4/41/NestedSetModel.svg/701px-NestedSetModel.svg.png) 8 | 9 | The result must be: 10 | 11 | | Node | Left | Right | Depth | 12 | |---------------|------|--------|-------| 13 | |Clothing | 1 | 22 | 0 | 14 | |Men's | 2 | 9 | 1 | 15 | |Women's | 10 | 21 | 1 | 16 | |Suits | 3 | 8 | 2 | 17 | |Slacks | 4 | 5 | 3 | 18 | |Jackets | 6 | 7 | 3 | 19 | |Dresses | 11 | 16 | 2 | 20 | |Skirts | 17 | 18 | 2 | 21 | |Blouses | 19 | 20 | 2 | 22 | |Evening Gowns | 12 | 13 | 3 | 23 | |Sun Dresses | 14 | 15 | 3 | 24 | 25 | ## Function 26 | 27 | ```php 28 | function convert_to_nested_tree($items, &$left = 1, $depth = 0) { 29 | if (count($items) > 0) { 30 | foreach ($items as &$item) { 31 | $item['depth'] = $depth; 32 | $item['left'] = $left++; 33 | if (count($item['children']) > 0) { 34 | $item['children'] = convert_to_nested_tree($item['children'], $left, $depth + 1); 35 | } 36 | $item['right'] = $left++; 37 | } 38 | } 39 | return $items; 40 | } 41 | ``` 42 | 43 | ### Example of usage 44 | 45 | ```php 46 | $items = array( 47 | array( 48 | 'name' => 'clothing', 49 | 'children' => array( 50 | array( 51 | 'name' => 'Men\'s', 52 | 'children' => array( 53 | array( 54 | 'name' => 'Suits', 55 | 'children' => array( 56 | array( 57 | 'name' => 'Slacks', 58 | ), 59 | array( 60 | 'name' => 'Jackets', 61 | ), 62 | ), 63 | ), 64 | ), 65 | ), 66 | array( 67 | 'name' => 'Women\'s', 68 | 'children' => array( 69 | array( 70 | 'name' => 'Dresses', 71 | 'children' => array( 72 | array( 73 | 'name' => 'Evening gowns', 74 | ), 75 | array( 76 | 'name' => 'Sun dresses', 77 | ), 78 | ), 79 | ), 80 | array( 81 | 'name' => 'Skirts', 82 | ), 83 | array( 84 | 'name' => 'Blouses', 85 | ), 86 | ), 87 | ), 88 | ), 89 | ), 90 | ); 91 | $result = convert_to_nested_tree($items); 92 | ``` 93 | 94 | ![Result](http://i.imgur.com/u9yPxxE.png) -------------------------------------------------------------------------------- /PHP/russian_plural.md: -------------------------------------------------------------------------------- 1 | # Russian Plural. 2 | 3 | This is plural function for Russian words. 4 | 5 | ~~~php 6 | /** 7 | * Plural function for Russian words. 8 | */ 9 | function russian_plural($number, $endingArray) { 10 | $number = abs($number) % 100; 11 | if ($number >= 11 && $number <= 19) { 12 | $ending = $endingArray[2]; 13 | } 14 | else { 15 | $i = $number % 10; 16 | switch ($i) { 17 | case (0): 18 | $ending = $endingArray[2]; 19 | break; 20 | case (1): 21 | $ending = $endingArray[0]; 22 | break; 23 | case (2): 24 | case (3): 25 | case (4): 26 | $ending = $endingArray[1]; 27 | break; 28 | default: 29 | $ending = $endingArray[2]; 30 | } 31 | } 32 | return $ending; 33 | } 34 | 35 | ~~~ 36 | 37 | ## Example 38 | 39 | ~~~php 40 | /** 41 | * @example 42 | */ 43 | $endings = [ 44 | 'яблоко', 45 | 'яблока', 46 | 'яблок', 47 | ]; 48 | print '1 ' . russian_plural(1, $endings); // 1 яблоко 49 | print '2 ' . russian_plural(2, $endings); // 2 яблока 50 | print '5 ' . russian_plural(5, $endings); // 5 яблок 51 | ~~~ 52 | 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Trash 2 | 3 | URL: http://niklan.github.io/Trash/ 4 | 5 | This is repository for store my own ugly or not code. Just small functions, tips, tricks for PHP, JS, HTML/CSS and ofcourse Drupal. 6 | 7 | I made it, because some task move from project to another and wirte same code again is painful and boring, same as find it backups. 8 | 9 | 10 | ## Categories 11 | 12 | * [Drupal](https://github.com/Niklan/Trash/tree/master/Drupal) 13 | 14 | By Nikita Malyshev (Niklan) 15 | http://niklan.net (hello@niklan.net) 16 | 17 | All what you find in this repository under WTFPL license. 18 | -------------------------------------------------------------------------------- /VMs/docker/drupal_console_in_dockerizeddrupal.md: -------------------------------------------------------------------------------- 1 | # How to use Drupal Console in dockerized drupal. 2 | 3 | ``` 4 | docker exec -it PROJECTNAME_php_1 bash -l 5 | su -l container 6 | cd /apache/data 7 | ``` 8 | 9 | Thats it, here you can used `drupal` command from drupal console. 10 | -------------------------------------------------------------------------------- /VMs/docker/import_mysql_to_container.md: -------------------------------------------------------------------------------- 1 | # How to import MySQL database dump to docker container 2 | 3 | Find MySQL container ID 4 | 5 | ~~~bash 6 | docker ps 7 | ~~~ 8 | 9 | F.e. 10 | 11 | ~~~bash 12 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 13 | dac45cf128f6 dockerizedrupal/apache-2.4:1.2.3 "/src/entrypoint.sh r" About an hour ago Up About an hour 80/tcp, 443/tcp test_apache_1 14 | 7687de8f626d dockerizedrupal/php-5.6:1.2.9 "/src/entrypoint.sh r" About an hour ago Up About an hour 9000/tcp test_php_1 15 | a20fb38c2f2d dockerizedrupal/mysql:1.2.2 "/src/entrypoint.sh r" 5 weeks ago Up About an hour 3306/tcp test_mysql_1 16 | ~~~ 17 | 18 | My container ID is a20fb38c2f2d, so next is import dump 19 | 20 | ~~~bash 21 | docker exec -i CONTAINER_ID mysql -uUSERNAME -pPASSWORD DATABASE_NAME < BACKUPFILENAME.sql 22 | ~~~ 23 | 24 | ~~~bash 25 | docker exec -i a20fb38c2f2d mysql -uusername -p123qwerty main < backup.sql 26 | ~~~ 27 | 28 | 29 | From .sql.gz 30 | 31 | ```bash 32 | zcat /path/to/file.sql.gz | mysql -uusername -p123qwerty your_database 33 | ``` 34 | -------------------------------------------------------------------------------- /VMs/docker/move_docker_container_data.md: -------------------------------------------------------------------------------- 1 | I have separated kernel and home directory disk partition. Docker use kernel by default, this is not good, cuz it's not enough memory to store this amount of data. The simple way to save docker data on another parition. 2 | 3 | # Ubuntu 16.04 or more aka systemd 4 | 5 | ~~~ 6 | sudo nano /etc/docker/daemon.json 7 | ~~~ 8 | 9 | ~~~ 10 | { 11 | "graph": "/NEW_PATH" 12 | } 13 | ~~~ 14 | 15 | ~~~ 16 | sudo service docker restart 17 | ~~~ 18 | 19 | # Ubuntu 15.10 or less 20 | 21 | ~~~ 22 | sudo nano /etc/default/docer 23 | ~~~ 24 | 25 | ~~~ 26 | DOCKER_OPTS="-g /NEW_PATH" 27 | ~~~ 28 | 29 | # Hardcore way 30 | 31 | ~~~ 32 | docker ps -q | xargs docker kill 33 | stop docker 34 | cd /var/lib/docker/devicemapper/mnt 35 | umount ./* 36 | mv /var/lib/docker /NEW_PATH 37 | ln -s /NEW_PATH /var/lib/docker 38 | start docker 39 | ~~~ 40 | -------------------------------------------------------------------------------- /VestaCP/Amazon S3 backups.md: -------------------------------------------------------------------------------- 1 | # Upload Vesta backups on Amazon S3. 2 | 3 | * Login to SSH as root, or admin. 4 | * Install latest version of [s3cmd](https://github.com/s3tools/s3cmd) 5 | * Create file `s3backups` or name it like you want it. 6 | * Insert code into file: 7 | 8 | ~~~sh 9 | #!/bin/bash 10 | 11 | # Importing system variables 12 | source /etc/profile 13 | 14 | s3cmd sync --delete-removed /home/backup/*.tar s3://BUCKET-NAME/FOLDER/ --storage-class REDUCED_REDUNDANCY 15 | ~~~ 16 | 17 | Move this file to `/usr/local/vesta/bin/` 18 | 19 | Make this file executable 20 | ~~~sh 21 | chmod a+x s3backups 22 | ~~~ 23 | 24 | * Add this file to cron, how often you want to upload backups to Amazon S3. For me, it doing every day at 3PM. 25 | 26 | ![Cron](https://i.imgur.com/TXwHl8t.png) 27 | 28 | This will backup all files in /home/backup which has .tar file extension. This file will be uploaded as 'Reduced Redundancy' files, so their price will be lower. 29 | 30 | You can call this scrip manualy when you want it, use code like in cron: `sudo /usr/local/vesta/bin/s3backups`. 31 | -------------------------------------------------------------------------------- /VestaCP/CentOS and PHP7.md: -------------------------------------------------------------------------------- 1 | # VestaCP + CentOS + Nginx + PHP 7 2 | 3 | This is simple instruction how to upgrade php to 7.1 version on VestaCP using CentOS and nginx + php-fpm version of Vesta CP. 4 | 5 | **Do not use this instruction on apache server, and over OS's than CentOS 7.x+** 6 | 7 | _I don't guarantee that this will work for you, better test it on celan droplet before do that on production._ 8 | 9 | First things, first. For this instruction you must have enabled REMI repositories for CentOS. This is done by default Vesta installation, if you don't disable it manually. 10 | 11 | If you do so, than enable them: 12 | 13 | ~~~bash 14 | yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm 15 | yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm 16 | yum install yum-utils 17 | ~~~ 18 | 19 | ## Install PHP 7.2 20 | 21 | ~~~bash 22 | service php-fpm stop 23 | yum -y --enablerepo=remi install php72-php php72-php-pear php72-php-bcmath php72-php-pecl-jsond-devel php72-php-mysqlnd php72-php-gd php72-php-common php72-php-fpm php72-php-intl php72-php-cli php72-php php72-php-xml php72-php-opcache php72-php-pecl-apcu php72-php-pecl-jsond php72-php-pdo php72-php-gmp php72-php-process php72-php-pecl-imagick php72-php-devel php72-php-mbstring php72-php-pecl-zip 24 | # Link new php to default binary 25 | rm -f /usr/bin/php 26 | ln -s /usr/bin/php72 /usr/bin/php 27 | # Replace old PHP.ini with new one MAKE BACKUP BEFORE THAT IF YOU DO CHANGES. 28 | rm -f /etc/php.ini 29 | ln -s /etc/opt/remi/php72/php.ini /etc/php.ini 30 | ~~~ 31 | 32 | Test installation 33 | 34 | ~~~ 35 | php -v 36 | PHP 7.2.16 (cli) (built: Mar 5 2019 13:10:50) ( NTS ) 37 | Copyright (c) 1997-2018 The PHP Group 38 | Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies 39 | with Zend OPcache v7.2.16, Copyright (c) 1999-2018, by Zend Technologies 40 | ~~~ 41 | 42 | Additional configuration 43 | 44 | ~~~bash 45 | sudo nano /etc/opt/remi/php72/php-fpm.conf 46 | # Change include line in FPM configuration group (first) to 47 | include=/etc/php-fpm.d/*.conf 48 | service php72-php-fpm start 49 | # Re-link old services 50 | rm -f /usr/lib/systemd/system/php-fpm.service 51 | ln -s /usr/lib/systemd/system/php72-php-fpm.service /usr/lib/systemd/system/php-fpm.service 52 | systemctl daemon-reload 53 | service nginx restart 54 | ~~~ 55 | -------------------------------------------------------------------------------- /VestaCP/CentOS install NVM.md: -------------------------------------------------------------------------------- 1 | # How to install NVM on CentOS 7.x 2 | 3 | For latest version of NVM got to their [GitHub repo](https://github.com/creationix/nvm/releases) and set it in command below. 4 | 5 | `curl https://raw.githubusercontent.com/creationix/nvm/v0.33.0/install.sh | bash` 6 | 7 | `source ~/.bashrc` 8 | 9 | Check installation with 10 | 11 | `nvm --version` 12 | -------------------------------------------------------------------------------- /VestaCP/Install composer.md: -------------------------------------------------------------------------------- 1 | # Composer insallation 2 | 3 | ``` 4 | php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" 5 | php composer-setup.php 6 | php -r "unlink('composer-setup.php');" 7 | ``` 8 | 9 | If you want to make it global 10 | 11 | ``` 12 | sudo chmod +x composer.phar 13 | sudo mv composer.phar /usr/local/composer 14 | ``` 15 | -------------------------------------------------------------------------------- /VestaCP/drupal-nginx/README.md: -------------------------------------------------------------------------------- 1 | # Drupal Nginx config for VestaCP 2 | 3 | This guide just for apacheless version of VestaCP (php-fpm + nginx). 4 | 5 | After installation you will have two configs for Drupal 7 and 8, but they are useless, because they handle alot of Drupal specific logic. For example, after enabling clean url's, your image style generation will break. This means, all images not created earlier will be broken, cuz of wrong logic in nginx config which not handle it. Also, you can download all files by direct input them in URL. F.e. http://domain.com/modules/block/block.module will download the file with code. It's vulnerability as is. 6 | 7 | This config fix all this stuff, and much more. This is combination of origin vesta config and [perusio's](https://github.com/perusio/drupal-with-nginx). 8 | 9 | This configs not replace original, it's additional, you easly can delete them if you don't like. 10 | 11 | ## Installation 12 | 13 | 1. Log in to your server as root user via ssh or sftp. 14 | 2. Navigate to `cd /usr/local/vesta/data/templates/web/nginx/php-fpm`. 15 | 3. Download config for HTTP: `wget https://raw.githubusercontent.com/Niklan/Trash/master/VestaCP/drupal-nginx/drupal-ready.tpl` 16 | 4. Download config for HTTPS: `wget https://raw.githubusercontent.com/Niklan/Trash/master/VestaCP/drupal-nginx/drupal-ready.stpl` 17 | 5. Navigate to `cd /usr/local/vesta/data/templates/web/nginx`. 18 | 6. Download drupal.inc `wget https://raw.githubusercontent.com/Niklan/Trash/master/VestaCP/drupal-nginx/drupal.inc` 19 | 7. Go to VestaCP and select this config where you need it. 20 | 8. If you do it on existing domain, you must rebuild config for user. `/usr/local/vesta/bin/v-rebuild-web-domains USERNAME` where username is vestacp user which domain belongs to. It's necessary to do, or serverl will continue use config generated by previous selection. They not dynamicly changes. 21 | 22 | You can also put this two files via SFTP and place it to folder from second step. 23 | 24 | P.s. I'm just beginner at nginx, so my config may be not full, so you can help me to edit them. 25 | 26 | 27 | ## Download all configs 28 | 29 | ```bash 30 | wget https://raw.githubusercontent.com/Niklan/Trash/master/VestaCP/drupal-nginx/drupal-ready.stpl && wget https://raw.githubusercontent.com/Niklan/Trash/master/VestaCP/drupal-nginx/drupal-ready.tpl &&wget https://raw.githubusercontent.com/Niklan/Trash/master/VestaCP/drupal-nginx/drupal-ready-http-no-www.stpl && wget https://raw.githubusercontent.com/Niklan/Trash/master/VestaCP/drupal-nginx/drupal-ready-http-no-www.tpl && wget https://raw.githubusercontent.com/Niklan/Trash/master/VestaCP/drupal-nginx/drupal-ready-https-no-www.stpl && wget https://raw.githubusercontent.com/Niklan/Trash/master/VestaCP/drupal-nginx/drupal-ready-https-no-www.tpl 31 | ``` 32 | 33 | drupal-project all confings 34 | 35 | ```bash 36 | wget https://raw.githubusercontent.com/Niklan/Trash/master/VestaCP/drupal-nginx/drupal-project.tpl && 37 | wget https://raw.githubusercontent.com/Niklan/Trash/master/VestaCP/drupal-nginx/drupal-project.stpl && 38 | wget https://raw.githubusercontent.com/Niklan/Trash/master/VestaCP/drupal-nginx/drupal-project-http-no-www.tpl && 39 | wget https://raw.githubusercontent.com/Niklan/Trash/master/VestaCP/drupal-nginx/drupal-project-http-no-www.stpl && 40 | wget https://raw.githubusercontent.com/Niklan/Trash/master/VestaCP/drupal-nginx/drupal-project-https-no-www.tpl && 41 | wget https://raw.githubusercontent.com/Niklan/Trash/master/VestaCP/drupal-nginx/drupal-project-https-no-www.stpl 42 | ``` 43 | -------------------------------------------------------------------------------- /VestaCP/drupal-nginx/drupal-project-http-no-www.stpl: -------------------------------------------------------------------------------- 1 | server { 2 | listen %ip%:%web_ssl_port% ssl http2; 3 | server_name %domain_idn% %alias_idn%; 4 | return 301 http://%domain_idn%$request_uri; 5 | } 6 | -------------------------------------------------------------------------------- /VestaCP/drupal-nginx/drupal-project-http-no-www.tpl: -------------------------------------------------------------------------------- 1 | server { 2 | listen %ip%:%web_port%; 3 | server_name %alias_idn%; 4 | return 301 http://%domain_idn%$request_uri; 5 | } 6 | 7 | server { 8 | listen %ip%:%web_port%; 9 | server_name %domain_idn%; 10 | root %docroot%/web; 11 | index index.php index.html index.htm; 12 | access_log /var/log/nginx/domains/%domain%.log combined; 13 | access_log /var/log/nginx/domains/%domain%.bytes bytes; 14 | error_log /var/log/nginx/domains/%domain%.error.log error; 15 | 16 | location ~ [^/]\.php(/|$) { 17 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 18 | if (!-f $document_root$fastcgi_script_name) { 19 | return 404; 20 | } 21 | 22 | fastcgi_pass %backend_lsnr%; 23 | fastcgi_index index.php; 24 | fastcgi_param SCRIPT_FILENAME $request_filename; 25 | fastcgi_intercept_errors on; 26 | fastcgi_buffer_size 32k; 27 | fastcgi_buffers 4 32k; 28 | include /etc/nginx/fastcgi_params; 29 | } 30 | 31 | error_page 403 /error/403.html; 32 | error_page 404 /error/404.html; 33 | error_page 500 502 503 504 /error/50x.html; 34 | 35 | location /error/ { 36 | alias %home%/%user%/web/%domain%/document_errors/; 37 | } 38 | 39 | include /usr/local/vesta/data/templates/web/nginx/drupal.inc*; 40 | 41 | include /etc/nginx/conf.d/phpmyadmin.inc*; 42 | include /etc/nginx/conf.d/phppgadmin.inc*; 43 | include /etc/nginx/conf.d/webmail.inc*; 44 | 45 | include %home%/%user%/conf/web/nginx.%domain%.conf*; 46 | } 47 | -------------------------------------------------------------------------------- /VestaCP/drupal-nginx/drupal-project-https-no-www.stpl: -------------------------------------------------------------------------------- 1 | server { 2 | listen %ip%:%web_ssl_port% http2 ssl; 3 | server_name %alias_idn%; 4 | ssl on; 5 | ssl_certificate %ssl_pem%; 6 | ssl_certificate_key %ssl_key%; 7 | return 301 https://%domain_idn%$request_uri; 8 | } 9 | 10 | server { 11 | listen %ip%:%web_ssl_port% http2; 12 | server_name %domain_idn%; 13 | root %docroot%/web; 14 | index index.php index.html index.htm; 15 | access_log /var/log/nginx/domains/%domain%.log combined; 16 | access_log /var/log/nginx/domains/%domain%.bytes bytes; 17 | error_log /var/log/nginx/domains/%domain%.error.log error; 18 | 19 | ssl on; 20 | ssl_certificate %ssl_pem%; 21 | ssl_certificate_key %ssl_key%; 22 | 23 | location ~ [^/]\.php(/|$) { 24 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 25 | if (!-f $document_root$fastcgi_script_name) { 26 | return 404; 27 | } 28 | 29 | fastcgi_pass %backend_lsnr%; 30 | fastcgi_index index.php; 31 | fastcgi_param SCRIPT_FILENAME $request_filename; 32 | fastcgi_intercept_errors on; 33 | fastcgi_buffer_size 32k; 34 | fastcgi_buffers 4 32k; 35 | include /etc/nginx/fastcgi_params; 36 | } 37 | 38 | error_page 403 /error/403.html; 39 | error_page 404 /error/404.html; 40 | error_page 500 502 503 504 /error/50x.html; 41 | 42 | location /error/ { 43 | alias %home%/%user%/web/%domain%/document_errors/; 44 | } 45 | 46 | include /usr/local/vesta/data/templates/web/nginx/drupal.inc*; 47 | 48 | include /etc/nginx/conf.d/phpmyadmin.inc*; 49 | include /etc/nginx/conf.d/phppgadmin.inc*; 50 | include /etc/nginx/conf.d/webmail.inc*; 51 | 52 | include %home%/%user%/conf/web/nginx.%domain%.conf*; 53 | } 54 | -------------------------------------------------------------------------------- /VestaCP/drupal-nginx/drupal-project-https-no-www.tpl: -------------------------------------------------------------------------------- 1 | server { 2 | listen %ip%:%web_port%; 3 | server_name %domain_idn% %alias_idn%; 4 | return 301 https://%domain_idn%$request_uri; 5 | } 6 | -------------------------------------------------------------------------------- /VestaCP/drupal-nginx/drupal-project.stpl: -------------------------------------------------------------------------------- 1 | server { 2 | listen %ip%:%web_ssl_port% ssl http2; 3 | server_name %domain_idn% %alias_idn%; 4 | root %docroot%/web; 5 | index index.php index.html index.htm; 6 | access_log /var/log/nginx/domains/%domain%.log combined; 7 | access_log /var/log/nginx/domains/%domain%.bytes bytes; 8 | error_log /var/log/nginx/domains/%domain%.error.log error; 9 | 10 | ssl on; 11 | ssl_certificate %ssl_pem%; 12 | ssl_certificate_key %ssl_key%; 13 | 14 | location ~ [^/]\.php(/|$) { 15 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 16 | if (!-f $document_root$fastcgi_script_name) { 17 | return 404; 18 | } 19 | 20 | fastcgi_pass %backend_lsnr%; 21 | fastcgi_index index.php; 22 | fastcgi_param SCRIPT_FILENAME $request_filename; 23 | fastcgi_intercept_errors on; 24 | fastcgi_buffer_size 32k; 25 | fastcgi_buffers 4 32k; 26 | include /etc/nginx/fastcgi_params; 27 | } 28 | 29 | error_page 403 /error/403.html; 30 | error_page 404 /error/404.html; 31 | error_page 500 502 503 504 /error/50x.html; 32 | 33 | location /error/ { 34 | alias %home%/%user%/web/%domain%/document_errors/; 35 | } 36 | 37 | include /usr/local/vesta/data/templates/web/nginx/drupal.inc*; 38 | 39 | include /etc/nginx/conf.d/phpmyadmin.inc*; 40 | include /etc/nginx/conf.d/phppgadmin.inc*; 41 | include /etc/nginx/conf.d/webmail.inc*; 42 | 43 | include %home%/%user%/conf/web/nginx.%domain_idn%.conf*; 44 | } 45 | -------------------------------------------------------------------------------- /VestaCP/drupal-nginx/drupal-project.tpl: -------------------------------------------------------------------------------- 1 | server { 2 | listen %ip%:%web_port%; 3 | server_name %domain_idn% %alias_idn%; 4 | root %docroot%/web; 5 | index index.php index.html index.htm; 6 | access_log /var/log/nginx/domains/%domain%.log combined; 7 | access_log /var/log/nginx/domains/%domain%.bytes bytes; 8 | error_log /var/log/nginx/domains/%domain%.error.log error; 9 | 10 | location ~ [^/]\.php(/|$) { 11 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 12 | if (!-f $document_root$fastcgi_script_name) { 13 | return 404; 14 | } 15 | 16 | fastcgi_pass %backend_lsnr%; 17 | fastcgi_index index.php; 18 | fastcgi_param SCRIPT_FILENAME $request_filename; 19 | fastcgi_intercept_errors on; 20 | fastcgi_buffer_size 32k; 21 | fastcgi_buffers 4 32k; 22 | include /etc/nginx/fastcgi_params; 23 | } 24 | 25 | error_page 403 /error/403.html; 26 | error_page 404 /error/404.html; 27 | error_page 500 502 503 504 /error/50x.html; 28 | 29 | location /error/ { 30 | alias %home%/%user%/web/%domain%/document_errors/; 31 | } 32 | 33 | include /usr/local/vesta/data/templates/web/nginx/drupal.inc*; 34 | 35 | include /etc/nginx/conf.d/phpmyadmin.inc*; 36 | include /etc/nginx/conf.d/phppgadmin.inc*; 37 | include /etc/nginx/conf.d/webmail.inc*; 38 | 39 | include %home%/%user%/conf/web/nginx.%domain_idn%.conf*; 40 | } 41 | -------------------------------------------------------------------------------- /VestaCP/drupal-nginx/drupal-ready-http-no-www.stpl: -------------------------------------------------------------------------------- 1 | server { 2 | listen %ip%:%web_ssl_port% ssl http2; 3 | server_name %domain_idn% %alias_idn%; 4 | return 301 http://%domain_idn%$request_uri; 5 | } 6 | -------------------------------------------------------------------------------- /VestaCP/drupal-nginx/drupal-ready-http-no-www.tpl: -------------------------------------------------------------------------------- 1 | server { 2 | listen %ip%:%web_port%; 3 | server_name %alias_idn%; 4 | return 301 http://%domain_idn%$request_uri; 5 | } 6 | 7 | server { 8 | listen %ip%:%web_port%; 9 | server_name %domain_idn%; 10 | root %docroot%; 11 | index index.php index.html index.htm; 12 | access_log /var/log/nginx/domains/%domain%.log combined; 13 | access_log /var/log/nginx/domains/%domain%.bytes bytes; 14 | error_log /var/log/nginx/domains/%domain%.error.log error; 15 | 16 | location ~ [^/]\.php(/|$) { 17 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 18 | if (!-f $document_root$fastcgi_script_name) { 19 | return 404; 20 | } 21 | 22 | fastcgi_pass %backend_lsnr%; 23 | fastcgi_index index.php; 24 | fastcgi_param SCRIPT_FILENAME $request_filename; 25 | fastcgi_intercept_errors on; 26 | fastcgi_buffer_size 32k; 27 | fastcgi_buffers 4 32k; 28 | include /etc/nginx/fastcgi_params; 29 | } 30 | 31 | error_page 403 /error/403.html; 32 | error_page 404 /error/404.html; 33 | error_page 500 502 503 504 /error/50x.html; 34 | 35 | location /error/ { 36 | alias %home%/%user%/web/%domain%/document_errors/; 37 | } 38 | 39 | include /etc/nginx/conf.d/drupal.inc*; 40 | 41 | include /etc/nginx/conf.d/phpmyadmin.inc*; 42 | include /etc/nginx/conf.d/phppgadmin.inc*; 43 | include /etc/nginx/conf.d/webmail.inc*; 44 | 45 | include %home%/%user%/conf/web/nginx.%domain%.conf*; 46 | } 47 | -------------------------------------------------------------------------------- /VestaCP/drupal-nginx/drupal-ready-https-no-www.stpl: -------------------------------------------------------------------------------- 1 | server { 2 | listen %ip%:%web_ssl_port% http2 ssl; 3 | server_name %alias_idn%; 4 | ssl on; 5 | ssl_certificate %ssl_pem%; 6 | ssl_certificate_key %ssl_key%; 7 | return 301 https://%domain_idn%$request_uri; 8 | } 9 | 10 | server { 11 | listen %ip%:%web_ssl_port% http2; 12 | server_name %domain_idn%; 13 | root %docroot%; 14 | index index.php index.html index.htm; 15 | access_log /var/log/nginx/domains/%domain%.log combined; 16 | access_log /var/log/nginx/domains/%domain%.bytes bytes; 17 | error_log /var/log/nginx/domains/%domain%.error.log error; 18 | 19 | ssl on; 20 | ssl_certificate %ssl_pem%; 21 | ssl_certificate_key %ssl_key%; 22 | 23 | location ~ [^/]\.php(/|$) { 24 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 25 | if (!-f $document_root$fastcgi_script_name) { 26 | return 404; 27 | } 28 | 29 | fastcgi_pass %backend_lsnr%; 30 | fastcgi_index index.php; 31 | fastcgi_param SCRIPT_FILENAME $request_filename; 32 | fastcgi_intercept_errors on; 33 | fastcgi_buffer_size 32k; 34 | fastcgi_buffers 4 32k; 35 | include /etc/nginx/fastcgi_params; 36 | } 37 | 38 | error_page 403 /error/403.html; 39 | error_page 404 /error/404.html; 40 | error_page 500 502 503 504 /error/50x.html; 41 | 42 | location /error/ { 43 | alias %home%/%user%/web/%domain%/document_errors/; 44 | } 45 | 46 | include /usr/local/vesta/data/templates/web/nginx/drupal.inc*; 47 | 48 | include /etc/nginx/conf.d/phpmyadmin.inc*; 49 | include /etc/nginx/conf.d/phppgadmin.inc*; 50 | include /etc/nginx/conf.d/webmail.inc*; 51 | 52 | include %home%/%user%/conf/web/nginx.%domain%.conf*; 53 | } 54 | -------------------------------------------------------------------------------- /VestaCP/drupal-nginx/drupal-ready-https-no-www.tpl: -------------------------------------------------------------------------------- 1 | server { 2 | listen %ip%:%web_port%; 3 | server_name %domain_idn% %alias_idn%; 4 | return 301 https://%domain_idn%$request_uri; 5 | } 6 | -------------------------------------------------------------------------------- /VestaCP/drupal-nginx/drupal-ready.stpl: -------------------------------------------------------------------------------- 1 | server { 2 | listen %ip%:%web_ssl_port% ssl http2; 3 | server_name %domain_idn% %alias_idn%; 4 | root %docroot%; 5 | index index.php index.html index.htm; 6 | access_log /var/log/nginx/domains/%domain%.log combined; 7 | access_log /var/log/nginx/domains/%domain%.bytes bytes; 8 | error_log /var/log/nginx/domains/%domain%.error.log error; 9 | 10 | ssl on; 11 | ssl_certificate %ssl_pem%; 12 | ssl_certificate_key %ssl_key%; 13 | 14 | location ~ [^/]\.php(/|$) { 15 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 16 | if (!-f $document_root$fastcgi_script_name) { 17 | return 404; 18 | } 19 | 20 | fastcgi_pass %backend_lsnr%; 21 | fastcgi_index index.php; 22 | fastcgi_param SCRIPT_FILENAME $request_filename; 23 | fastcgi_intercept_errors on; 24 | fastcgi_buffer_size 32k; 25 | fastcgi_buffers 4 32k; 26 | include /etc/nginx/fastcgi_params; 27 | } 28 | 29 | error_page 403 /error/403.html; 30 | error_page 404 /error/404.html; 31 | error_page 500 502 503 504 /error/50x.html; 32 | 33 | location /error/ { 34 | alias %home%/%user%/web/%domain%/document_errors/; 35 | } 36 | 37 | include /usr/local/vesta/data/templates/web/nginx/drupal.inc*; 38 | 39 | include /etc/nginx/conf.d/phpmyadmin.inc*; 40 | include /etc/nginx/conf.d/phppgadmin.inc*; 41 | include /etc/nginx/conf.d/webmail.inc*; 42 | 43 | include %home%/%user%/conf/web/nginx.%domain_idn%.conf*; 44 | } 45 | -------------------------------------------------------------------------------- /VestaCP/drupal-nginx/drupal-ready.tpl: -------------------------------------------------------------------------------- 1 | server { 2 | listen %ip%:%web_port%; 3 | server_name %domain_idn% %alias_idn%; 4 | root %docroot%; 5 | index index.php index.html index.htm; 6 | access_log /var/log/nginx/domains/%domain%.log combined; 7 | access_log /var/log/nginx/domains/%domain%.bytes bytes; 8 | error_log /var/log/nginx/domains/%domain%.error.log error; 9 | 10 | location ~ [^/]\.php(/|$) { 11 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 12 | if (!-f $document_root$fastcgi_script_name) { 13 | return 404; 14 | } 15 | 16 | fastcgi_pass %backend_lsnr%; 17 | fastcgi_index index.php; 18 | fastcgi_param SCRIPT_FILENAME $request_filename; 19 | fastcgi_intercept_errors on; 20 | fastcgi_buffer_size 32k; 21 | fastcgi_buffers 4 32k; 22 | include /etc/nginx/fastcgi_params; 23 | } 24 | 25 | error_page 403 /error/403.html; 26 | error_page 404 /error/404.html; 27 | error_page 500 502 503 504 /error/50x.html; 28 | 29 | location /error/ { 30 | alias %home%/%user%/web/%domain%/document_errors/; 31 | } 32 | 33 | include /usr/local/vesta/data/templates/web/nginx/drupal.inc*; 34 | 35 | include /etc/nginx/conf.d/phpmyadmin.inc*; 36 | include /etc/nginx/conf.d/phppgadmin.inc*; 37 | include /etc/nginx/conf.d/webmail.inc*; 38 | 39 | include %home%/%user%/conf/web/nginx.%domain_idn%.conf*; 40 | } 41 | -------------------------------------------------------------------------------- /VestaCP/drupal-nginx/drupal.inc: -------------------------------------------------------------------------------- 1 | location / { 2 | # Very rarely should these ever be accessed outside of your lan 3 | location ~* \.(txt|log)$ { 4 | allow 192.168.0.0/16; 5 | deny all; 6 | } 7 | 8 | # Trying to access private files directly returns a 404. 9 | location ^~ /sites/default/files/private/ { 10 | internal; 11 | } 12 | 13 | # For configuration storage. 14 | location ^~ /sites/configurations/ { 15 | internal; 16 | } 17 | 18 | # Don't allow direct access to PHP files in the vendor directory. 19 | location ~ /vendor/.*\.php$ { 20 | deny all; 21 | return 404; 22 | } 23 | 24 | # Fix for image style generation. 25 | location ~ ^/sites/.*/files/styles/ { 26 | try_files $uri @drupal; 27 | access_log off; 28 | expires max; 29 | ## No need to bleed constant updates. Send the all shebang in one 30 | ## fell swoop. 31 | tcp_nodelay off; 32 | ## Set the OS file cache. 33 | open_file_cache max=3000 inactive=120s; 34 | open_file_cache_valid 45s; 35 | open_file_cache_min_uses 2; 36 | open_file_cache_errors off; 37 | } 38 | 39 | # Handle private files through Drupal. 40 | location ~ ^/system/files/ { # For Drupal >= 7 41 | try_files $uri /index.php?$query_string; 42 | } 43 | 44 | # Advanced Aggregation module CSS 45 | # support. http://drupal.org/project/advagg. 46 | location ^~ /sites/default/files/advagg_css/ { 47 | expires max; 48 | add_header ETag ''; 49 | add_header Last-Modified 'Wed, 20 Jan 1988 04:20:42 GMT'; 50 | add_header Accept-Ranges ''; 51 | 52 | location ~* ^/sites/default/files/advagg_css/css[__[:alnum:]]+\.css$ { 53 | allow all; 54 | access_log off; 55 | try_files $uri @drupal; 56 | } 57 | } 58 | 59 | # Advanced Aggregation module JS 60 | # support. http://drupal.org/project/advagg. 61 | location ^~ /sites/default/files/advagg_js/ { 62 | expires max; 63 | add_header ETag ''; 64 | add_header Last-Modified 'Wed, 20 Jan 1988 04:20:42 GMT'; 65 | add_header Accept-Ranges ''; 66 | 67 | location ~* ^/sites/default/files/advagg_js/js[__[:alnum:]]+\.js$ { 68 | access_log off; 69 | try_files $uri @drupal; 70 | } 71 | } 72 | 73 | # All static files will be served directly. 74 | location ~* ^.+\.(?:css|cur|js|jpe?g|gif|htc|ico|png|html|otf|ttf|eot|woff2?|svg)$ { 75 | access_log off; 76 | expires max; 77 | # No need to bleed constant updates. Send the all shebang in one 78 | # fell swoop. 79 | tcp_nodelay off; 80 | # Set the OS file cache. 81 | open_file_cache max=3000 inactive=120s; 82 | open_file_cache_valid 45s; 83 | open_file_cache_min_uses 2; 84 | open_file_cache_errors off; 85 | } 86 | 87 | # Replicate the Apache directive of Drupal standard 88 | # .htaccess. Disable access to any code files. Return a 404 to curtail 89 | # information disclosure. Hide also the text files. 90 | location ~* ^(?:.+\.(?:htaccess|make|txt|engine|inc|info|install|module|profile|po|pot|sh|.*sql|test|theme|tpl(?:\.php)?|xtmpl)|code-style\.pl|/Entries.*|/Repository|/Root|/Tag|/Template)$ { 91 | return 404; 92 | } 93 | 94 | try_files $uri @drupal; 95 | } 96 | 97 | location = /favicon.ico { 98 | log_not_found off; 99 | access_log off; 100 | access_log off; 101 | expires max; 102 | # No need to bleed constant updates. Send the all shebang in one 103 | # fell swoop. 104 | tcp_nodelay off; 105 | # Set the OS file cache. 106 | open_file_cache max=3000 inactive=120s; 107 | open_file_cache_valid 45s; 108 | open_file_cache_min_uses 2; 109 | open_file_cache_errors off; 110 | } 111 | 112 | # With robotstxt module support. 113 | location = /robots.txt { 114 | allow all; 115 | log_not_found off; 116 | access_log off; 117 | try_files $uri @drupal; 118 | } 119 | 120 | location = /humans.txt { 121 | allow all; 122 | log_not_found off; 123 | access_log off; 124 | } 125 | 126 | # XML Dynamic support 127 | location ~* \.xml { 128 | try_files $uri @drupal; 129 | } 130 | 131 | # Disallow access to .bzr, .git, .hg, .svn, .cvs directories: return 132 | # 404 as not to disclose information. 133 | location ^~ /.bzr { 134 | return 404; 135 | } 136 | 137 | location ^~ /.git { 138 | return 404; 139 | } 140 | 141 | location ^~ /.hg { 142 | return 404; 143 | } 144 | 145 | location ^~ /.svn { 146 | return 404; 147 | } 148 | 149 | location ^~ /.cvs { 150 | return 404; 151 | } 152 | 153 | # Disallow access to patches directory. 154 | location ^~ /patches { 155 | return 404; 156 | } 157 | 158 | # Any other attempt to access PHP files returns a 404. 159 | location ~* ^.+\.php$ { 160 | return 404; 161 | } 162 | 163 | location @drupal { 164 | rewrite ^/(.*)$ /index.php; 165 | } 166 | -------------------------------------------------------------------------------- /VestaCP/drush-wrapper-for-composer.md: -------------------------------------------------------------------------------- 1 | # Drush wrapper for composer 2 | 3 | ## Simple and elegant solution 4 | 5 | [Drush Launcher](https://github.com/drush-ops/drush-launcher) 6 | 7 | ## Global 8 | 9 | 1. `touch /usr/local/bin/drush` 10 | 2. `vi /usr/local/bin/drush` 11 | 3. 12 | ```bash 13 | #!/usr/bin/env sh 14 | # 15 | # A wrapper script which launches the Drush that is in your project's /vendor 16 | # directory. 17 | # 18 | ./vendor/bin/drush --local $@ 19 | ``` -------------------------------------------------------------------------------- /VestaCP/php-fpm.conf.md: -------------------------------------------------------------------------------- 1 | # php-fpm.conf 2 | 3 | Use [this service](https://cmorrell.com/php-fpm/) to calculate your best settings. 4 | 5 | This will calculate optimal for performance php-fpm settings. 6 | 7 | VestaCP uses templates for each domain, so you need to create new template for this and use it for needed domains. 8 | 9 | ## Create template 10 | 11 | 1. Navigate to php-fpm templataes `cd /usr/local/vesta/data/templates/web/php-fpm` 12 | 1. Create new file, e.g. `touch performance.conf`. 13 | 1. Fill it with data and save. 14 | 15 | E.g.: 16 | 17 | ```conf 18 | ; https://cmorrell.com/php-fpm/ 19 | [%backend%] 20 | listen = 127.0.0.1:%backend_port% 21 | listen.allowed_clients = 127.0.0.1 22 | 23 | user = %user% 24 | group = %user% 25 | 26 | ; Run php-fpm in "dynamic" mode 27 | pm = dynamic 28 | ; Set max_children to ([total RAM - reserved RAM]) / [average php-fpm process]) 29 | ; Most recently: (1024 * (2 - 1)) / 60 = 17 30 | pm.max_children = 15 31 | ; After this many requests, a php-fpm process will respawn. This is useful 32 | ; to guard against memory leaks, but causes a small performance hit. Set to 33 | ; a high number (or 0) if you're confident that your app does not have any 34 | ; memory leaks (and that you're not using any 3rd-party libraries that have 35 | ; memory leaks), or set to a lower number if you're aware of a leak. 36 | pm.max_requests = 500 37 | ; When php-fpm starts, have this many processes waiting for requests. Set to 50% of 38 | ; max on a server that's mostly responsible for running PHP processes 39 | pm.start_servers = 5 40 | ; Minimum number spare processes php-fpm will create. In the case of a 41 | ; server dedicated to running PHP, we'll set this to the same as start_servers 42 | pm.min_spare_servers = 5 43 | ; Maximum number spare processes php-fpm will create. If more than this 44 | ; many processes are idle, some will be killed. 45 | pm.max_spare_servers = 10 46 | pm.process_idle_timeout = 10s 47 | pm.status_path = /status 48 | 49 | php_admin_value[upload_tmp_dir] = /home/%user%/tmp 50 | php_admin_value[session.save_path] = /home/%user%/tmp 51 | 52 | env[HOSTNAME] = $HOSTNAME 53 | env[PATH] = /usr/local/bin:/usr/bin:/bin 54 | env[TMP] = /home/%user%/tmp 55 | env[TMPDIR] = /home/%user%/tmp 56 | env[TEMP] = /home/%user%/tmp 57 | ``` 58 | 59 | Then go to web domain settings and select it. 60 | 61 | ![Settings](https://i.imgur.com/K6AJDaU.png) 62 | -------------------------------------------------------------------------------- /centminmod/installation.md: -------------------------------------------------------------------------------- 1 | 2 | ## swap 3 | 4 | ``` 5 | sudo fallocate -l 1G /swapfile 6 | sudo chmod 600 /swapfile 7 | sudo mkswap /swapfile 8 | sudo swapon /swapfile 9 | sudo nano /etc/fstab 10 | ``` 11 | 12 | ``` 13 | /swapfile swap swap sw 0 0 14 | ``` 15 | 16 | ## Installation 17 | 18 | 1. Disable SELINUX 19 | 20 | ``` 21 | vi /etc/selinux/config 22 | ``` 23 | 24 | ``` 25 | SELINUX=enforcing 26 | 27 | to 28 | 29 | SELINUX=disabled 30 | ``` 31 | 32 | and reboot system. 33 | 34 | 2. Install centmin Mod stable 35 | 36 | ``` 37 | yum -y update; curl -O https://centminmod.com/installer.sh && chmod 0700 installer.sh && bash installer.sh 38 | ``` 39 | 40 | 3. Use it `centmin`. -------------------------------------------------------------------------------- /docker-based-vps/Projects/README.md: -------------------------------------------------------------------------------- 1 | # README 2 | 3 | The current folder is base Project folder to configure reverse proxy which will route all requests to specific projects. 4 | 5 | ## docker-compose.yml 6 | 7 | This docker compose file is simple, we define single service - traefik. We include `traefik.yml` file with our settings into image and expose two ports. 8 | 9 | We also create here a custom network named `web` and attach traefik container to it. This network will be used only by containers that want to be access from public web. 10 | 11 | ### traefik.yml 12 | 13 | Traefik is configured to listen `:80` (HTTP) and `:443` (HTTPS) ports. That means any other connection to a different port will be handled by hoist system and ignored by Traefik. Open new ports with caution. 14 | 15 | ### providers.docker.exposedByDefault: false 16 | 17 | By default docker provider exposed by default. This means that all docker container up and running will be visible to Traefik and it will generate default routing and other settings for them. 18 | 19 | We disable that behavior because it creates a lot of unused settings and can potentially lead to security problems. 20 | 21 | We will explicitly expose only trusted containers to Traefik. 22 | 23 | ### certificatesResolvers.letsencrypt 24 | 25 | We configure certificate provider `letsencrypt` which wil lbe used as free certificate generator. You should change email to your own, or most likely it wont work because of API limits. 26 | 27 | ## Examples 28 | 29 | * [example-1.com](https://github.com/Niklan/Trash/tree/master/docker-based-vps/Projects/example-1.com): The most simplistic example with Traefik whoami. 30 | * [example-2.com](https://github.com/Niklan/Trash/tree/master/docker-based-vps/Projects/example-2.com): This example show how to serve simple static HTML website with NGINX. 31 | * [example-3.com](https://github.com/Niklan/Trash/tree/master/docker-based-vps/Projects/example-3.com): This example shows how to serve simple PHP application with `index.php`. 32 | * [example-4.com](https://github.com/Niklan/Trash/tree/master/docker-based-vps/Projects/example-4.com): This example shows how to configure project for Drupal. On top of PHP and NGINX container here is added MariaDB for database. 33 | * [example-5.com](https://github.com/Niklan/Trash/tree/master/docker-based-vps/Projects/example-5.com): The most complex example. As addition for example-4.com adds SSH keys for deployments, node container for compiling CSS and JS and configure system cron. -------------------------------------------------------------------------------- /docker-based-vps/Projects/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | traefik: 5 | container_name: traefik 6 | restart: always 7 | image: traefik:v2.5 8 | ports: 9 | - "80:80" 10 | - "443:443" 11 | networks: 12 | - web 13 | volumes: 14 | - /var/run/docker.sock:/var/run/docker.sock 15 | - ./traefik.yml:/etc/traefik/traefik.yml 16 | 17 | networks: 18 | web: 19 | name: web -------------------------------------------------------------------------------- /docker-based-vps/Projects/example-1.com/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | whoami: 5 | restart: unless-stopped 6 | image: "traefik/whoami" 7 | networks: 8 | - web 9 | labels: 10 | - traefik.enable=true 11 | # HTTP router. 12 | - traefik.http.routers.example_1_whoami_http.rule=Host(`example-1.com`) 13 | - traefik.http.routers.example_1_whoami_http.entrypoints=http 14 | # HTTPS router. 15 | - traefik.http.routers.example_1_whoami_https.tls=true 16 | - traefik.http.routers.example_1_whoami_https.rule=Host(`example-1.com`) 17 | - traefik.http.routers.example_1_whoami_https.entrypoints=https 18 | - traefik.http.routers.example_1_whoami_https.tls.certresolver=letsencrypt 19 | # HTTP → HTTPS redirect. 20 | - traefik.http.middlewares.whoami_redirect_to_https.redirectscheme.scheme=https 21 | - traefik.http.routers.example_1_whoami_http.middlewares=whoami_redirect_to_https@docker 22 | 23 | networks: 24 | web: 25 | external: true 26 | -------------------------------------------------------------------------------- /docker-based-vps/Projects/example-2.com/.env: -------------------------------------------------------------------------------- 1 | PROJECT_NAME=example_2 2 | PROJECT_BASE_URL=example-2.com 3 | 4 | NGINX_TAG=1.19-5.10.11 5 | NGINX_VHOST_PRESET=html 6 | -------------------------------------------------------------------------------- /docker-based-vps/Projects/example-2.com/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | nginx: 5 | restart: unless-stopped 6 | image: wodby/nginx:$NGINX_TAG 7 | container_name: "${PROJECT_NAME}_nginx" 8 | depends_on: 9 | - php 10 | environment: 11 | NGINX_VHOST_PRESET: $NGINX_VHOST_PRESET 12 | volumes: 13 | - ./www:/var/www/html 14 | labels: 15 | - traefik.enable=true 16 | - traefik.http.routers.${PROJECT_NAME}_nginx_http.rule=Host(`${PROJECT_BASE_URL}`) 17 | - traefik.http.routers.${PROJECT_NAME}_nginx_http.entrypoints=http 18 | - traefik.http.routers.${PROJECT_NAME}_nginx_https.rule=Host(`${PROJECT_BASE_URL}`) 19 | - traefik.http.routers.${PROJECT_NAME}_nginx_https.entrypoints=https 20 | - traefik.http.routers.${PROJECT_NAME}_nginx_https.tls=true 21 | - traefik.http.routers.${PROJECT_NAME}_nginx_https.tls.certresolver=letsencrypt 22 | - traefik.http.middlewares.${PROJECT_NAME}_nginx_redirect_to_https.redirectscheme.scheme=https 23 | - traefik.http.routers.${PROJECT_NAME}_nginx_http.middlewares=${PROJECT_NAME}_nginx_redirect_to_https@docker 24 | networks: 25 | - web 26 | 27 | networks: 28 | web: 29 | external: true 30 | -------------------------------------------------------------------------------- /docker-based-vps/Projects/example-2.com/www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello Docker! 6 | 7 | 8 |

It's worked!

9 | 10 | -------------------------------------------------------------------------------- /docker-based-vps/Projects/example-3.com/.env: -------------------------------------------------------------------------------- 1 | PROJECT_NAME=example_3 2 | PROJECT_BASE_URL=example-3.com 3 | 4 | PHP_TAG=8.0-4.21.4 5 | NGINX_TAG=1.19-5.10.11 6 | NGINX_VHOST_PRESET=php 7 | -------------------------------------------------------------------------------- /docker-based-vps/Projects/example-3.com/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | php: 5 | restart: unless-stopped 6 | image: wodby/php:$PHP_TAG 7 | container_name: "${PROJECT_NAME}_php" 8 | volumes: 9 | - ./www:/var/www/html 10 | networks: 11 | - project 12 | 13 | nginx: 14 | restart: unless-stopped 15 | image: wodby/nginx:$NGINX_TAG 16 | container_name: "${PROJECT_NAME}_nginx" 17 | depends_on: 18 | - php 19 | environment: 20 | NGINX_BACKEND_HOST: php 21 | NGINX_VHOST_PRESET: $NGINX_VHOST_PRESET 22 | volumes: 23 | - ./www:/var/www/html 24 | labels: 25 | - traefik.enable=true 26 | - traefik.docker.network=web 27 | - traefik.http.routers.${PROJECT_NAME}_nginx_http.rule=Host(`${PROJECT_BASE_URL}`) 28 | - traefik.http.routers.${PROJECT_NAME}_nginx_http.entrypoints=http 29 | - traefik.http.routers.${PROJECT_NAME}_nginx_https.rule=Host(`${PROJECT_BASE_URL}`) 30 | - traefik.http.routers.${PROJECT_NAME}_nginx_https.entrypoints=https 31 | - traefik.http.routers.${PROJECT_NAME}_nginx_https.tls=true 32 | - traefik.http.routers.${PROJECT_NAME}_nginx_https.tls.certresolver=letsencrypt 33 | - traefik.http.middlewares.${PROJECT_NAME}_nginx_redirect_to_https.redirectscheme.scheme=https 34 | - traefik.http.routers.${PROJECT_NAME}_nginx_http.middlewares=${PROJECT_NAME}_nginx_redirect_to_https@docker 35 | networks: 36 | - web 37 | - project 38 | 39 | networks: 40 | web: 41 | external: true 42 | project: 43 | external: false 44 | name: "${PROJECT_NAME}_network" -------------------------------------------------------------------------------- /docker-based-vps/Projects/example-3.com/www/index.php: -------------------------------------------------------------------------------- 1 | ./dump.sql.gz 41 | " 42 | 43 | echo "Sync project files." 44 | rsync \ 45 | -avz \ 46 | --delete \ 47 | --exclude /database \ 48 | $SERVER_USERNAME@$SERVER_HOST:$PROJECT_PATH/ \ 49 | $MIRROR_DIR 50 | 51 | echo "The backup is saved at: $MIRROR_DIR" 52 | notify-send 'Backup' 'Backup script finished!' 53 | sleep 3 54 | ``` 55 | 56 | ### What does this script do 57 | 58 | * Creates special localhost directory where backup will be stored. 59 | * Using SSH connection it will create a database dump in project folder from the `mariadb` container. 60 | * Using `rsync` it will transfer all project directory folders and files (except `/database` which is bind-mount of DB) to your local directory. 61 | * This script only downloads new or updated files on second+ runs, also it will remove an outdated files which is not presented on remote anymore. 62 | 63 | ### How to configure script 64 | 65 | * `$PROJECT_NAME`: The product name. This name will be used to navigate into project remote directory and as directory name for backup on localhost. 66 | * `$PROJECT_PATH`: The directory with project (where `docker-compose.yml` and `.env` files are located). This is a directory, the contents of which will be backup. 67 | * `$MIRROR_DIR`: The localhost destination path to save backup files. 68 | * `$SERVER_USERNAME`: The username of a remote server. 69 | * `$SERVER_HOST`: The hostname or IP of a remote server. 70 | 71 | ## Backup to remote 72 | 73 | Below, you can find an example script to create separate code and database backups for Drupal ([example-5.com](Projects/example-5.com/README.md)). 74 | 75 | This script creates backups and upload them to S3 Compatible object storage clouds (Amazon S3, Yandex Object Storage etc). 76 | 77 | You can adjust any its settings, by default: 78 | 79 | - It creates folder per backup type inside `BACKUP_DIRECTORY`: 80 | - `daily/`: 7 in total. Monday backup will be overriden by new on next week. 81 | - `weekly/`: 4 in total. Each week of the month will have its own backup. 82 | - `monthly/`: 12 in total. Each month of the year will have its own backup. January backup will be overriden by new on next yer. 83 | - `yearly/`: Not limited by default. If this backup script will work for 5 year, it will have 5 backups for each year. 84 | - It uses [s3cmd](https://github.com/s3tools/s3cmd) tool to upload backups. 85 | - It expects that you have separate `.s3cfg` per project placed at the same dir as this script (`S3CMD_CONFIG`). 86 | - This script is better to be places on per-project basis to adjust it for project needs. E.g. `Projects/example-5.com/scripts/backup.sh`. 87 | - It better to run from system (user) crontab instead of docker. You can find examples inside it. 88 | 89 | You can find additional information inside script comments. Don't forget to update variable `S3_BUCKET_URI` for your needs. 90 | 91 | ```bash 92 | #!/usr/bin/env bash 93 | 94 | # This script will create backup of the project and upload it on remote server. 95 | # 96 | # Available options: 97 | # -d: For daily backup. 98 | # -w: For weekly backup. 99 | # -m: For monthly backup. 100 | # -y: For yearly backup. 101 | # 102 | # Examples. 103 | # 104 | # Create a daily backup: 105 | # $ bash backup.sh -d 106 | # 107 | # Create a weekly backup: 108 | # $ bash backup.sh -w 109 | # 110 | # Create a monthly backup: 111 | # $ bash backup.sh -m 112 | # 113 | # Create a yearly backup: 114 | # $ bash backup.sh -y 115 | # 116 | # Backup filenames will use numbers in their filename to avoid duplicating files 117 | # and will override the old one on next backup. 118 | # 119 | # E.g. for daily backup filename will be 'database-$DAY.sql.gz' where $DAY - number 120 | # of the week from 0 to 6, where 0 is Sunday. For Monday it will be 1, which means 121 | # every Monday this backup will be named 'database-1.sql.gz' and uploaded to remote 122 | # server overriding previous file with the same name. This way you don't need to 123 | # delete an old backups. 124 | # 125 | # Same logic applied for other parameters. 126 | # 127 | # Use it in crontab (crontab -e): 128 | # 129 | # For daily backups at 00:00: 130 | # '0 0 * * * /usr/bin/bash /path/to/backup.sh -d' 131 | # 132 | # For weekly backups at 01:00 on Sunday: 133 | # '0 1 * * 0 /usr/bin/bash /path/to/backup.sh -w' 134 | # 135 | # For monthly backups at 02:00 on 1 day of month 136 | # '0 2 1 * * /usr/bin/bash /path/to/backup.sh -m' 137 | # 138 | # For yearly backups at 03:00 on 1th January. 139 | # '0 3 1 1 * /usr/bin/bash /path/to/backup.sh -y' 140 | 141 | # For crontab. 142 | export TERM=xterm 143 | set -e 144 | set +x 145 | 146 | # Settings for backup script. 147 | # A path where is current script is placed. 148 | SCRIPT_PATH=$(realpath $(dirname "$0")); 149 | # A path where is project root is located. 150 | PROJECT_PATH="$SCRIPT_PATH/.." 151 | # A path to directory, where backups should be saved. 152 | BACKUP_DIRECTORY="$PROJECT_PATH/backups" 153 | # A path to directry with codebase. 154 | CODEBASE_DIRECTORY="$PROJECT_PATH/www" 155 | # A path for s3cmd tool configuration. This is used to upload to S3 compatible storages. 156 | S3CMD_CONFIG=$SCRIPT_PATH/.s3cfg 157 | # An URI for root backet for backups. 158 | S3_BUCKET_URI=s3://example-5.com/backups 159 | # A list of tables from Drupal to be exported with structure only. 160 | # This reduces dabase dump size significantly. 161 | STRUCTURE_TABLES_LIST=(cache,cache_*,flood,history,queue,search_index,search_api_*,semaphore,sequences,sessions,watchdog) 162 | # A paramter for drush combines structure tables above. 163 | DRUSH_STRUCTURE_TABLES_LIST='' 164 | for TABLE in "${STRUCTURE_TABLES_LIST[@]}" 165 | do : 166 | DRUSH_STRUCTURE_TABLES_LIST+=" --structure-tables-list=${TABLE}" 167 | done 168 | 169 | # Provides the function for backup project and upload it in remote storage. 170 | backup() { 171 | cd "$PROJECT_PATH" 172 | 173 | echo "Make sure destination directory is exists." 174 | mkdir -p "$PROJECT_PATH" 175 | 176 | echo "Make sure backup directory is exists." 177 | mkdir -p "$BACKUP_DIRECTORY" 178 | 179 | echo "Prepare a database dump." 180 | docker compose exec -T -e DRUSH_STRUCTURE_TABLES_LIST="$DRUSH_STRUCTURE_TABLES_LIST" php sh -c 'drush sql:dump --gzip $DRUSH_STRUCTURE_TABLES_LIST' > $BACKUP_DIRECTORY/$DATABASE_FILENAME 181 | 182 | echo "Upload database backup." 183 | s3cmd -c "$S3CMD_CONFIG" --storage-class COLD put "$BACKUP_DIRECTORY/$DATABASE_FILENAME" "$S3_BACKUP_URI/$DATABASE_FILENAME" 184 | 185 | echo "Prepare a codabase archive." 186 | tar -czf "$BACKUP_DIRECTORY/$CODEBASE_FILENAME" "$CODEBASE_DIRECTORY" 187 | 188 | echo "Upload codebase backup." 189 | s3cmd -c "$S3CMD_CONFIG" --storage-class COLD put "$BACKUP_DIRECTORY/$CODEBASE_FILENAME" "$S3_BACKUP_URI/$CODEBASE_FILENAME" 190 | 191 | echo "Clean up local files." 192 | rm -rf "$BACKUP_DIRECTORY" 193 | } 194 | 195 | while getopts "dwmy" arg; do 196 | case $arg in 197 | d) 198 | S3_BACKUP_URI="$S3_BUCKET_URI/daily" 199 | DAY=$(date +%w) 200 | DATABASE_FILENAME="database-$DAY.sql.gz" 201 | CODEBASE_FILENAME="codebase-$DAY.tar.gz" 202 | backup 203 | ;; 204 | w) 205 | S3_BACKUP_URI="$S3_BUCKET_URI/weekly" 206 | # Use code below if you want backup for each week of the year. 207 | #WEEK=$(date +%U) 208 | # The code below get week of the month. Assuming that Monday is 209 | # first day of the week (remove '+1' if you want Sunday). 210 | WEEK=$((($(date +%-d)-1)/7+1)) 211 | DATABASE_FILENAME="database-$WEEK.sql.gz" 212 | CODEBASE_FILENAME="codebase-$WEEK.tar.gz" 213 | backup 214 | ;; 215 | m) 216 | S3_BACKUP_URI="$S3_BUCKET_URI/monthly" 217 | MONTH=$(date +%m) 218 | DATABASE_FILENAME="database-$MONTH.sql.gz" 219 | CODEBASE_FILENAME="codebase-$MONTH.tar.gz" 220 | backup 221 | ;; 222 | y) 223 | S3_BACKUP_URI="$S3_BUCKET_URI/yearly" 224 | YEAR=$(date +%Y) 225 | DATABASE_FILENAME="database-$YEAR.sql.gz" 226 | CODEBASE_FILENAME="codebase-$YEAR.tar.gz" 227 | backup 228 | ;; 229 | *) 230 | exit 0 231 | ;; 232 | esac 233 | done 234 | 235 | ``` --------------------------------------------------------------------------------