3708 lines
264 KiB
HTML
3708 lines
264 KiB
HTML
|
<!DOCTYPE html><html lang="fr">
|
|||
|
<head><meta charset="utf-8">
|
|||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|||
|
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"><title>Guide d'installation Nextcloud 17 et plus (Debian / NGINX) - YannStatic</title>
|
|||
|
|
|||
|
<meta name="description" content="Guide d’installation Nextcloud 17 et plus (Debian / NGINX)">
|
|||
|
<link rel="canonical" href="https://static.rnmkcy.eu/2020/01/20/Guide-installation-Nextcloud-17-(Debian-NGINX).html"><link rel="alternate" type="application/rss+xml" title="YannStatic" href="/feed.xml">
|
|||
|
|
|||
|
<!-- - include head/favicon.html - -->
|
|||
|
<link rel="shortcut icon" type="image/png" href="/assets/favicon/favicon.png"><link rel="stylesheet" href="/assets/css/main.css"><link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" ><!-- start custom head snippets --><link rel="stylesheet" href="/assets/css/expand.css">
|
|||
|
<!-- end custom head snippets --><script>(function() {
|
|||
|
window.isArray = function(val) {
|
|||
|
return Object.prototype.toString.call(val) === '[object Array]';
|
|||
|
};
|
|||
|
window.isString = function(val) {
|
|||
|
return typeof val === 'string';
|
|||
|
};
|
|||
|
|
|||
|
window.hasEvent = function(event) {
|
|||
|
return 'on'.concat(event) in window.document;
|
|||
|
};
|
|||
|
|
|||
|
window.isOverallScroller = function(node) {
|
|||
|
return node === document.documentElement || node === document.body || node === window;
|
|||
|
};
|
|||
|
|
|||
|
window.isFormElement = function(node) {
|
|||
|
var tagName = node.tagName;
|
|||
|
return tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA';
|
|||
|
};
|
|||
|
|
|||
|
window.pageLoad = (function () {
|
|||
|
var loaded = false, cbs = [];
|
|||
|
window.addEventListener('load', function () {
|
|||
|
var i;
|
|||
|
loaded = true;
|
|||
|
if (cbs.length > 0) {
|
|||
|
for (i = 0; i < cbs.length; i++) {
|
|||
|
cbs[i]();
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
return {
|
|||
|
then: function(cb) {
|
|||
|
cb && (loaded ? cb() : (cbs.push(cb)));
|
|||
|
}
|
|||
|
};
|
|||
|
})();
|
|||
|
})();
|
|||
|
(function() {
|
|||
|
window.throttle = function(func, wait) {
|
|||
|
var args, result, thisArg, timeoutId, lastCalled = 0;
|
|||
|
|
|||
|
function trailingCall() {
|
|||
|
lastCalled = new Date;
|
|||
|
timeoutId = null;
|
|||
|
result = func.apply(thisArg, args);
|
|||
|
}
|
|||
|
return function() {
|
|||
|
var now = new Date,
|
|||
|
remaining = wait - (now - lastCalled);
|
|||
|
|
|||
|
args = arguments;
|
|||
|
thisArg = this;
|
|||
|
|
|||
|
if (remaining <= 0) {
|
|||
|
clearTimeout(timeoutId);
|
|||
|
timeoutId = null;
|
|||
|
lastCalled = now;
|
|||
|
result = func.apply(thisArg, args);
|
|||
|
} else if (!timeoutId) {
|
|||
|
timeoutId = setTimeout(trailingCall, remaining);
|
|||
|
}
|
|||
|
return result;
|
|||
|
};
|
|||
|
};
|
|||
|
})();
|
|||
|
(function() {
|
|||
|
var Set = (function() {
|
|||
|
var add = function(item) {
|
|||
|
var i, data = this._data;
|
|||
|
for (i = 0; i < data.length; i++) {
|
|||
|
if (data[i] === item) {
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
this.size ++;
|
|||
|
data.push(item);
|
|||
|
return data;
|
|||
|
};
|
|||
|
|
|||
|
var Set = function(data) {
|
|||
|
this.size = 0;
|
|||
|
this._data = [];
|
|||
|
var i;
|
|||
|
if (data.length > 0) {
|
|||
|
for (i = 0; i < data.length; i++) {
|
|||
|
add.call(this, data[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
Set.prototype.add = add;
|
|||
|
Set.prototype.get = function(index) { return this._data[index]; };
|
|||
|
Set.prototype.has = function(item) {
|
|||
|
var i, data = this._data;
|
|||
|
for (i = 0; i < data.length; i++) {
|
|||
|
if (this.get(i) === item) {
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
return false;
|
|||
|
};
|
|||
|
Set.prototype.is = function(map) {
|
|||
|
if (map._data.length !== this._data.length) { return false; }
|
|||
|
var i, j, flag, tData = this._data, mData = map._data;
|
|||
|
for (i = 0; i < tData.length; i++) {
|
|||
|
for (flag = false, j = 0; j < mData.length; j++) {
|
|||
|
if (tData[i] === mData[j]) {
|
|||
|
flag = true;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
if (!flag) { return false; }
|
|||
|
}
|
|||
|
return true;
|
|||
|
};
|
|||
|
Set.prototype.values = function() {
|
|||
|
return this._data;
|
|||
|
};
|
|||
|
return Set;
|
|||
|
})();
|
|||
|
|
|||
|
window.Lazyload = (function(doc) {
|
|||
|
var queue = {js: [], css: []}, sources = {js: {}, css: {}}, context = this;
|
|||
|
var createNode = function(name, attrs) {
|
|||
|
var node = doc.createElement(name), attr;
|
|||
|
for (attr in attrs) {
|
|||
|
if (attrs.hasOwnProperty(attr)) {
|
|||
|
node.setAttribute(attr, attrs[attr]);
|
|||
|
}
|
|||
|
}
|
|||
|
return node;
|
|||
|
};
|
|||
|
var end = function(type, url) {
|
|||
|
var s, q, qi, cbs, i, j, cur, val, flag;
|
|||
|
if (type === 'js' || type ==='css') {
|
|||
|
s = sources[type], q = queue[type];
|
|||
|
s[url] = true;
|
|||
|
for (i = 0; i < q.length; i++) {
|
|||
|
cur = q[i];
|
|||
|
if (cur.urls.has(url)) {
|
|||
|
qi = cur, val = qi.urls.values();
|
|||
|
qi && (cbs = qi.callbacks);
|
|||
|
for (flag = true, j = 0; j < val.length; j++) {
|
|||
|
cur = val[j];
|
|||
|
if (!s[cur]) {
|
|||
|
flag = false;
|
|||
|
}
|
|||
|
}
|
|||
|
if (flag && cbs && cbs.length > 0) {
|
|||
|
for (j = 0; j < cbs.length; j++) {
|
|||
|
cbs[j].call(context);
|
|||
|
}
|
|||
|
qi.load = true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
var load = function(type, urls, callback) {
|
|||
|
var s, q, qi, node, i, cur,
|
|||
|
_urls = typeof urls === 'string' ? new Set([urls]) : new Set(urls), val, url;
|
|||
|
if (type === 'js' || type ==='css') {
|
|||
|
s = sources[type], q = queue[type];
|
|||
|
for (i = 0; i < q.length; i++) {
|
|||
|
cur = q[i];
|
|||
|
if (_urls.is(cur.urls)) {
|
|||
|
qi = cur;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
val = _urls.values();
|
|||
|
if (qi) {
|
|||
|
callback && (qi.load || qi.callbacks.push(callback));
|
|||
|
callback && (qi.load && callback());
|
|||
|
} else {
|
|||
|
q.push({
|
|||
|
urls: _urls,
|
|||
|
callbacks: callback ? [callback] : [],
|
|||
|
load: false
|
|||
|
});
|
|||
|
for (i = 0; i < val.length; i++) {
|
|||
|
node = null, url = val[i];
|
|||
|
if (s[url] === undefined) {
|
|||
|
(type === 'js' ) && (node = createNode('script', { src: url }));
|
|||
|
(type === 'css') && (node = createNode('link', { rel: 'stylesheet', href: url }));
|
|||
|
if (node) {
|
|||
|
node.onload = (function(type, url) {
|
|||
|
return function() {
|
|||
|
end(type, url);
|
|||
|
};
|
|||
|
})(type, url);
|
|||
|
(doc.head || doc.body).appendChild(node);
|
|||
|
s[url] = false;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
return {
|
|||
|
js: function(url, callback) {
|
|||
|
load('js', url, callback);
|
|||
|
},
|
|||
|
css: function(url, callback) {
|
|||
|
load('css', url, callback);
|
|||
|
}
|
|||
|
};
|
|||
|
})(this.document);
|
|||
|
})();
|
|||
|
</script><script>
|
|||
|
(function() {
|
|||
|
var TEXT_VARIABLES = {
|
|||
|
version: '2.2.6',
|
|||
|
sources: {
|
|||
|
font_awesome: 'https://use.fontawesome.com/releases/v5.0.13/css/all.css',
|
|||
|
jquery: '/assets/js/jquery.min.js',
|
|||
|
leancloud_js_sdk: '//cdn.jsdelivr.net/npm/leancloud-storage@3.13.2/dist/av-min.js',
|
|||
|
chart: 'https://cdn.bootcss.com/Chart.js/2.7.2/Chart.bundle.min.js',
|
|||
|
gitalk: {
|
|||
|
js: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.js',
|
|||
|
css: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.css'
|
|||
|
},
|
|||
|
valine: 'https://unpkg.com/valine/dist/Valine.min.js'
|
|||
|
},
|
|||
|
site: {
|
|||
|
toc: {
|
|||
|
selectors: 'h1,h2,h3'
|
|||
|
}
|
|||
|
},
|
|||
|
paths: {
|
|||
|
search_js: '/assets/search.js'
|
|||
|
}
|
|||
|
};
|
|||
|
window.TEXT_VARIABLES = TEXT_VARIABLES;
|
|||
|
})();
|
|||
|
</script>
|
|||
|
</head>
|
|||
|
<body>
|
|||
|
<div class="root" data-is-touch="false">
|
|||
|
<div class="layout--page js-page-root"><!----><div class="page__main js-page-main page__viewport hide-footer has-aside has-aside cell cell--auto">
|
|||
|
|
|||
|
<div class="page__main-inner"><div class="page__header d-print-none"><header class="header"><div class="main">
|
|||
|
<div class="header__title">
|
|||
|
<div class="header__brand"><svg id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="478.9473684210526" viewBox="0, 0, 400,478.9473684210526"><g id="svgg"><path id="path0" d="M308.400 56.805 C 306.970 56.966,303.280 57.385,300.200 57.738 C 290.906 58.803,278.299 59.676,269.200 59.887 L 260.600 60.085 259.400 61.171 C 258.010 62.428,256.198 63.600,255.645 63.600 C 255.070 63.600,252.887 65.897,252.598 66.806 C 252.460 67.243,252.206 67.600,252.034 67.600 C 251.397 67.600,247.206 71.509,247.202 72.107 C 247.201 72.275,246.390 73.190,245.400 74.138 C 243.961 75.517,243.598 76.137,243.592 77.231 C 243.579 79.293,241.785 83.966,240.470 85.364 C 239.176 86.740,238.522 88.365,237.991 91.521 C 237.631 93.665,236.114 97.200,235.554 97.200 C 234.938 97.200,232.737 102.354,232.450 104.472 C 232.158 106.625,230.879 109.226,229.535 110.400 C 228.933 110.926,228.171 113.162,226.434 119.500 C 226.178 120.435,225.795 121.200,225.584 121.200 C 225.373 121.200,225.200 121.476,225.200 121.813 C 225.200 122.149,224.885 122.541,224.500 122.683 C 223.606 123.013,223.214 123.593,223.204 124.600 C 223.183 126.555,220.763 132.911,219.410 134.562 C 218.443 135.742,217.876 136.956,217.599 138.440 C 217.041 141.424,215.177 146.434,214.532 146.681 C 214.240 146.794,214.000 147.055,214.000 147.261 C 214.000 147.467,213.550 148.086,213.000 148.636 C 212.450 149.186,212.000 149.893,212.000 150.208 C 212.000 151.386,208.441 154.450,207.597 153.998 C 206.319 153.315,204.913 150.379,204.633 147.811 C 204.365 145.357,202.848 142.147,201.759 141.729 C 200.967 141.425,199.200 137.451,199.200 135.974 C 199.200 134.629,198.435 133.224,196.660 131.311 C 195.363 129.913,194.572 128.123,193.870 125.000 C 193.623 123.900,193.236 122.793,193.010 122.540 C 190.863 120.133,190.147 118.880,188.978 115.481 C 188.100 112.928,187.151 111.003,186.254 109.955 C 185.358 108.908,184.518 107.204,183.847 105.073 C 183.280 103.273,182.497 101.329,182.108 100.753 C 181.719 100.177,180.904 98.997,180.298 98.131 C 179.693 97.265,178.939 95.576,178.624 94.378 C 178.041 92.159,177.125 90.326,175.023 87.168 C 174.375 86.196,173.619 84.539,173.342 83.486 C 172.800 81.429,171.529 79.567,170.131 78.785 C 169.654 78.517,168.697 77.511,168.006 76.549 C 167.316 75.587,166.594 74.800,166.402 74.800 C 166.210 74.800,164.869 73.633,163.421 72.206 C 160.103 68.936,161.107 69.109,146.550 69.301 C 133.437 69.474,128.581 70.162,126.618 72.124 C 126.248 72.495,125.462 72.904,124.872 73.033 C 124.282 73.163,123.088 73.536,122.219 73.863 C 121.349 74.191,119.028 74.638,117.061 74.858 C 113.514 75.254,109.970 76.350,108.782 77.419 C 107.652 78.436,100.146 80.400,97.388 80.400 C 95.775 80.400,93.167 81.360,91.200 82.679 C 90.430 83.195,89.113 83.804,88.274 84.031 C 85.875 84.681,78.799 90.910,74.400 96.243 L 73.400 97.456 73.455 106.028 C 73.526 117.055,74.527 121.238,77.820 124.263 C 78.919 125.273,80.400 127.902,80.400 128.842 C 80.400 129.202,81.075 130.256,81.900 131.186 C 83.563 133.059,85.497 136.346,86.039 138.216 C 86.233 138.886,87.203 140.207,88.196 141.153 C 89.188 142.098,90.000 143.104,90.000 143.388 C 90.000 144.337,92.129 148.594,92.869 149.123 C 93.271 149.410,93.600 149.831,93.600 150.059 C 93.600 150.286,93.932 150.771,94.337 151.136 C 94.743 151.501,95.598 153.004,96.237 154.475 C 96.877 155.947,97.760 157.351,98.200 157.596 C 98.640 157.841,99.900 159.943,101.000 162.267 C 102.207 164.817,103.327 166.644,103.825 166.876 C 104.278 167.087,105.065 168.101,105.573 169.130 C 107.658 173.348,108.097 174.093,110.006 176.647 C 111.103 178.114,112.000 179.725,112.000 180.227 C 112.000 181.048,113.425 183.163,114.678 184.200 C 115.295 184.711,117.396 188.733,117.720 190.022 C 117.855 190.562,118.603 191.633,119.381 192.402 C 120.160 193.171,121.496 195.258,122.351 197.039 C 123.206 198.820,124.167 200.378,124.487 200.501 C 124.807 200.624,125.953 202.496,127.034 204.662 C 128.114 206.828,129.676 209.299,130.505 210.153 C 131.333 211.007,132.124 212.177,132.262 212.753 C 132.618 214.239,134.291 217.048,136.288 219.5
|
|||
|
" href="/">YannStatic</a></div><!--<button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button>--><!-- <li><button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button></li> -->
|
|||
|
<!-- Champ de recherche -->
|
|||
|
<div id="searchbox" class="search search--dark" style="visibility: visible">
|
|||
|
<div class="main">
|
|||
|
<div class="search__header"></div>
|
|||
|
<div class="search-bar">
|
|||
|
<div class="search-box js-search-box">
|
|||
|
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
|
|||
|
<input id="search-input" type="text" />
|
|||
|
<!-- <div class="search-box__icon-clear js-icon-clear">
|
|||
|
<a><i class="fas fa-times"></i></a>
|
|||
|
</div> -->
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<!-- Script pointing to search-script.js -->
|
|||
|
<script>/*!
|
|||
|
* Simple-Jekyll-Search
|
|||
|
* Copyright 2015-2020, Christian Fei
|
|||
|
* Licensed under the MIT License.
|
|||
|
*/
|
|||
|
|
|||
|
(function(){
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$Templater_7 = {
|
|||
|
compile: compile,
|
|||
|
setOptions: setOptions
|
|||
|
}
|
|||
|
|
|||
|
const options = {}
|
|||
|
options.pattern = /\{(.*?)\}/g
|
|||
|
options.template = ''
|
|||
|
options.middleware = function () {}
|
|||
|
|
|||
|
function setOptions (_options) {
|
|||
|
options.pattern = _options.pattern || options.pattern
|
|||
|
options.template = _options.template || options.template
|
|||
|
if (typeof _options.middleware === 'function') {
|
|||
|
options.middleware = _options.middleware
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function compile (data) {
|
|||
|
return options.template.replace(options.pattern, function (match, prop) {
|
|||
|
const value = options.middleware(prop, data[prop], options.template)
|
|||
|
if (typeof value !== 'undefined') {
|
|||
|
return value
|
|||
|
}
|
|||
|
return data[prop] || match
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
'use strict';
|
|||
|
|
|||
|
function fuzzysearch (needle, haystack) {
|
|||
|
var tlen = haystack.length;
|
|||
|
var qlen = needle.length;
|
|||
|
if (qlen > tlen) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
if (qlen === tlen) {
|
|||
|
return needle === haystack;
|
|||
|
}
|
|||
|
outer: for (var i = 0, j = 0; i < qlen; i++) {
|
|||
|
var nch = needle.charCodeAt(i);
|
|||
|
while (j < tlen) {
|
|||
|
if (haystack.charCodeAt(j++) === nch) {
|
|||
|
continue outer;
|
|||
|
}
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
var _$fuzzysearch_1 = fuzzysearch;
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
|
|||
|
|
|||
|
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
|
|||
|
|
|||
|
function FuzzySearchStrategy () {
|
|||
|
this.matches = function (string, crit) {
|
|||
|
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
|
|||
|
|
|||
|
function LiteralSearchStrategy () {
|
|||
|
this.matches = function (str, crit) {
|
|||
|
if (!str) return false
|
|||
|
|
|||
|
str = str.trim().toLowerCase()
|
|||
|
crit = crit.trim().toLowerCase()
|
|||
|
|
|||
|
return crit.split(' ').filter(function (word) {
|
|||
|
return str.indexOf(word) >= 0
|
|||
|
}).length === crit.split(' ').length
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$Repository_4 = {
|
|||
|
put: put,
|
|||
|
clear: clear,
|
|||
|
search: search,
|
|||
|
setOptions: __setOptions_4
|
|||
|
}
|
|||
|
|
|||
|
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
|
|||
|
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
|
|||
|
|
|||
|
function NoSort () {
|
|||
|
return 0
|
|||
|
}
|
|||
|
|
|||
|
const data = []
|
|||
|
let opt = {}
|
|||
|
|
|||
|
opt.fuzzy = false
|
|||
|
opt.limit = 10
|
|||
|
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
|
|||
|
opt.sort = NoSort
|
|||
|
opt.exclude = []
|
|||
|
|
|||
|
function put (data) {
|
|||
|
if (isObject(data)) {
|
|||
|
return addObject(data)
|
|||
|
}
|
|||
|
if (isArray(data)) {
|
|||
|
return addArray(data)
|
|||
|
}
|
|||
|
return undefined
|
|||
|
}
|
|||
|
function clear () {
|
|||
|
data.length = 0
|
|||
|
return data
|
|||
|
}
|
|||
|
|
|||
|
function isObject (obj) {
|
|||
|
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
|
|||
|
}
|
|||
|
|
|||
|
function isArray (obj) {
|
|||
|
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
|
|||
|
}
|
|||
|
|
|||
|
function addObject (_data) {
|
|||
|
data.push(_data)
|
|||
|
return data
|
|||
|
}
|
|||
|
|
|||
|
function addArray (_data) {
|
|||
|
const added = []
|
|||
|
clear()
|
|||
|
for (let i = 0, len = _data.length; i < len; i++) {
|
|||
|
if (isObject(_data[i])) {
|
|||
|
added.push(addObject(_data[i]))
|
|||
|
}
|
|||
|
}
|
|||
|
return added
|
|||
|
}
|
|||
|
|
|||
|
function search (crit) {
|
|||
|
if (!crit) {
|
|||
|
return []
|
|||
|
}
|
|||
|
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
|
|||
|
}
|
|||
|
|
|||
|
function __setOptions_4 (_opt) {
|
|||
|
opt = _opt || {}
|
|||
|
|
|||
|
opt.fuzzy = _opt.fuzzy || false
|
|||
|
opt.limit = _opt.limit || 10
|
|||
|
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
|
|||
|
opt.sort = _opt.sort || NoSort
|
|||
|
opt.exclude = _opt.exclude || []
|
|||
|
}
|
|||
|
|
|||
|
function findMatches (data, crit, strategy, opt) {
|
|||
|
const matches = []
|
|||
|
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
|
|||
|
const match = findMatchesInObject(data[i], crit, strategy, opt)
|
|||
|
if (match) {
|
|||
|
matches.push(match)
|
|||
|
}
|
|||
|
}
|
|||
|
return matches
|
|||
|
}
|
|||
|
|
|||
|
function findMatchesInObject (obj, crit, strategy, opt) {
|
|||
|
for (const key in obj) {
|
|||
|
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
|
|||
|
return obj
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function isExcluded (term, excludedTerms) {
|
|||
|
for (let i = 0, len = excludedTerms.length; i < len; i++) {
|
|||
|
const excludedTerm = excludedTerms[i]
|
|||
|
if (new RegExp(excludedTerm).test(term)) {
|
|||
|
return true
|
|||
|
}
|
|||
|
}
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
/* globals ActiveXObject:false */
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$JSONLoader_2 = {
|
|||
|
load: load
|
|||
|
}
|
|||
|
|
|||
|
function load (location, callback) {
|
|||
|
const xhr = getXHR()
|
|||
|
xhr.open('GET', location, true)
|
|||
|
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
|
|||
|
xhr.send()
|
|||
|
}
|
|||
|
|
|||
|
function createStateChangeListener (xhr, callback) {
|
|||
|
return function () {
|
|||
|
if (xhr.readyState === 4 && xhr.status === 200) {
|
|||
|
try {
|
|||
|
callback(null, JSON.parse(xhr.responseText))
|
|||
|
} catch (err) {
|
|||
|
callback(err, null)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function getXHR () {
|
|||
|
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$OptionsValidator_3 = function OptionsValidator (params) {
|
|||
|
if (!validateParams(params)) {
|
|||
|
throw new Error('-- OptionsValidator: required options missing')
|
|||
|
}
|
|||
|
|
|||
|
if (!(this instanceof OptionsValidator)) {
|
|||
|
return new OptionsValidator(params)
|
|||
|
}
|
|||
|
|
|||
|
const requiredOptions = params.required
|
|||
|
|
|||
|
this.getRequiredOptions = function () {
|
|||
|
return requiredOptions
|
|||
|
}
|
|||
|
|
|||
|
this.validate = function (parameters) {
|
|||
|
const errors = []
|
|||
|
requiredOptions.forEach(function (requiredOptionName) {
|
|||
|
if (typeof parameters[requiredOptionName] === 'undefined') {
|
|||
|
errors.push(requiredOptionName)
|
|||
|
}
|
|||
|
})
|
|||
|
return errors
|
|||
|
}
|
|||
|
|
|||
|
function validateParams (params) {
|
|||
|
if (!params) {
|
|||
|
return false
|
|||
|
}
|
|||
|
return typeof params.required !== 'undefined' && params.required instanceof Array
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$utils_9 = {
|
|||
|
merge: merge,
|
|||
|
isJSON: isJSON
|
|||
|
}
|
|||
|
|
|||
|
function merge (defaultParams, mergeParams) {
|
|||
|
const mergedOptions = {}
|
|||
|
for (const option in defaultParams) {
|
|||
|
mergedOptions[option] = defaultParams[option]
|
|||
|
if (typeof mergeParams[option] !== 'undefined') {
|
|||
|
mergedOptions[option] = mergeParams[option]
|
|||
|
}
|
|||
|
}
|
|||
|
return mergedOptions
|
|||
|
}
|
|||
|
|
|||
|
function isJSON (json) {
|
|||
|
try {
|
|||
|
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
|
|||
|
return true
|
|||
|
}
|
|||
|
return false
|
|||
|
} catch (err) {
|
|||
|
return false
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var _$src_8 = {};
|
|||
|
(function (window) {
|
|||
|
'use strict'
|
|||
|
|
|||
|
let options = {
|
|||
|
searchInput: null,
|
|||
|
resultsContainer: null,
|
|||
|
json: [],
|
|||
|
success: Function.prototype,
|
|||
|
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
|
|||
|
templateMiddleware: Function.prototype,
|
|||
|
sortMiddleware: function () {
|
|||
|
return 0
|
|||
|
},
|
|||
|
noResultsText: 'No results found',
|
|||
|
limit: 10,
|
|||
|
fuzzy: false,
|
|||
|
debounceTime: null,
|
|||
|
exclude: []
|
|||
|
}
|
|||
|
|
|||
|
let debounceTimerHandle
|
|||
|
const debounce = function (func, delayMillis) {
|
|||
|
if (delayMillis) {
|
|||
|
clearTimeout(debounceTimerHandle)
|
|||
|
debounceTimerHandle = setTimeout(func, delayMillis)
|
|||
|
} else {
|
|||
|
func.call()
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
|
|||
|
|
|||
|
/* removed: const _$Templater_7 = require('./Templater') */;
|
|||
|
/* removed: const _$Repository_4 = require('./Repository') */;
|
|||
|
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
|
|||
|
const optionsValidator = _$OptionsValidator_3({
|
|||
|
required: requiredOptions
|
|||
|
})
|
|||
|
/* removed: const _$utils_9 = require('./utils') */;
|
|||
|
|
|||
|
window.SimpleJekyllSearch = function (_options) {
|
|||
|
const errors = optionsValidator.validate(_options)
|
|||
|
if (errors.length > 0) {
|
|||
|
throwError('You must specify the following required options: ' + requiredOptions)
|
|||
|
}
|
|||
|
|
|||
|
options = _$utils_9.merge(options, _options)
|
|||
|
|
|||
|
_$Templater_7.setOptions({
|
|||
|
template: options.searchResultTemplate,
|
|||
|
middleware: options.templateMiddleware
|
|||
|
})
|
|||
|
|
|||
|
_$Repository_4.setOptions({
|
|||
|
fuzzy: options.fuzzy,
|
|||
|
limit: options.limit,
|
|||
|
sort: options.sortMiddleware,
|
|||
|
exclude: options.exclude
|
|||
|
})
|
|||
|
|
|||
|
if (_$utils_9.isJSON(options.json)) {
|
|||
|
initWithJSON(options.json)
|
|||
|
} else {
|
|||
|
initWithURL(options.json)
|
|||
|
}
|
|||
|
|
|||
|
const rv = {
|
|||
|
search: search
|
|||
|
}
|
|||
|
|
|||
|
typeof options.success === 'function' && options.success.call(rv)
|
|||
|
return rv
|
|||
|
}
|
|||
|
|
|||
|
function initWithJSON (json) {
|
|||
|
_$Repository_4.put(json)
|
|||
|
registerInput()
|
|||
|
}
|
|||
|
|
|||
|
function initWithURL (url) {
|
|||
|
_$JSONLoader_2.load(url, function (err, json) {
|
|||
|
if (err) {
|
|||
|
throwError('failed to get JSON (' + url + ')')
|
|||
|
}
|
|||
|
initWithJSON(json)
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function emptyResultsContainer () {
|
|||
|
options.resultsContainer.innerHTML = ''
|
|||
|
}
|
|||
|
|
|||
|
function appendToResultsContainer (text) {
|
|||
|
options.resultsContainer.innerHTML += text
|
|||
|
}
|
|||
|
|
|||
|
function registerInput () {
|
|||
|
options.searchInput.addEventListener('input', function (e) {
|
|||
|
if (isWhitelistedKey(e.which)) {
|
|||
|
emptyResultsContainer()
|
|||
|
debounce(function () { search(e.target.value) }, options.debounceTime)
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function search (query) {
|
|||
|
if (isValidQuery(query)) {
|
|||
|
emptyResultsContainer()
|
|||
|
render(_$Repository_4.search(query), query)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function render (results, query) {
|
|||
|
const len = results.length
|
|||
|
if (len === 0) {
|
|||
|
return appendToResultsContainer(options.noResultsText)
|
|||
|
}
|
|||
|
for (let i = 0; i < len; i++) {
|
|||
|
results[i].query = query
|
|||
|
appendToResultsContainer(_$Templater_7.compile(results[i]))
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function isValidQuery (query) {
|
|||
|
return query && query.length > 0
|
|||
|
}
|
|||
|
|
|||
|
function isWhitelistedKey (key) {
|
|||
|
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
|
|||
|
}
|
|||
|
|
|||
|
function throwError (message) {
|
|||
|
throw new Error('SimpleJekyllSearch --- ' + message)
|
|||
|
}
|
|||
|
})(window)
|
|||
|
|
|||
|
}());
|
|||
|
</script>
|
|||
|
|
|||
|
<!-- Configuration -->
|
|||
|
<script>
|
|||
|
SimpleJekyllSearch({
|
|||
|
searchInput: document.getElementById('search-input'),
|
|||
|
resultsContainer: document.getElementById('results-container'),
|
|||
|
json: '/search.json',
|
|||
|
//searchResultTemplate: '<li><a href="https://static.rnmkcy.eu{url}">{date} {title}</a></li>'
|
|||
|
searchResultTemplate: '<li><a href="{url}">{date} {title}</a></li>'
|
|||
|
})
|
|||
|
</script>
|
|||
|
<!-- Fin déclaration champ de recherche --></div><nav class="navigation">
|
|||
|
<ul><li class="navigation__item"><a href="/archive.html">Etiquettes</a></li><li class="navigation__item"><a href="/htmldoc.html">Documents</a></li><li class="navigation__item"><a href="/liens_ttrss.html">Liens</a></li><li class="navigation__item"><a href="/aide-jekyll-text-theme.html">Aide</a></li></ul>
|
|||
|
</nav></div>
|
|||
|
</header>
|
|||
|
|
|||
|
</div><div class="page__content"><div class ="main"><div class="grid grid--reverse">
|
|||
|
<div class="col-main cell cell--auto"><!-- start custom main top snippet --><div id="results-container" class="search-result js-search-result"></div><!-- end custom main top snippet -->
|
|||
|
<article itemscope itemtype="http://schema.org/Article"><div class="article__header"><header><h1 style="color:Tomato;">Guide d'installation Nextcloud 17 et plus (Debian / NGINX)</h1></header></div><meta itemprop="headline" content="Guide d'installation Nextcloud 17 et plus (Debian / NGINX)"><div class="article__info clearfix"><ul class="left-col menu"><li>
|
|||
|
<a class="button button--secondary button--pill button--sm"
|
|||
|
href="/archive.html?tag=nextcloud">nextcloud</a>
|
|||
|
</li></ul><ul class="right-col menu"><li>
|
|||
|
<i class="far fa-calendar-alt"></i> <span title="Création" style="color:#FF00FF">20 janv. 2020</span></li></ul></div><meta itemprop="datePublished" content="2020-01-20T00:00:00+01:00">
|
|||
|
<meta itemprop="keywords" content="nextcloud"><div class="js-article-content">
|
|||
|
<div class="layout--article"><!-- start custom article top snippet -->
|
|||
|
<style>
|
|||
|
#myBtn {
|
|||
|
display: none;
|
|||
|
position: fixed;
|
|||
|
bottom: 10px;
|
|||
|
right: 10px;
|
|||
|
z-index: 99;
|
|||
|
font-size: 12px;
|
|||
|
font-weight: bold;
|
|||
|
border: none;
|
|||
|
outline: none;
|
|||
|
background-color: white;
|
|||
|
color: black;
|
|||
|
cursor: pointer;
|
|||
|
padding: 5px;
|
|||
|
border-radius: 4px;
|
|||
|
}
|
|||
|
|
|||
|
#myBtn:hover {
|
|||
|
background-color: #555;
|
|||
|
}
|
|||
|
</style>
|
|||
|
|
|||
|
<button onclick="topFunction()" id="myBtn" title="Haut de page">⇧</button>
|
|||
|
|
|||
|
<script>
|
|||
|
//Get the button
|
|||
|
var mybutton = document.getElementById("myBtn");
|
|||
|
|
|||
|
// When the user scrolls down 20px from the top of the document, show the button
|
|||
|
window.onscroll = function() {scrollFunction()};
|
|||
|
|
|||
|
function scrollFunction() {
|
|||
|
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
|
|||
|
mybutton.style.display = "block";
|
|||
|
} else {
|
|||
|
mybutton.style.display = "none";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// When the user clicks on the button, scroll to the top of the document
|
|||
|
function topFunction() {
|
|||
|
document.body.scrollTop = 0;
|
|||
|
document.documentElement.scrollTop = 0;
|
|||
|
}
|
|||
|
</script>
|
|||
|
|
|||
|
|
|||
|
<!-- end custom article top snippet -->
|
|||
|
<div class="article__content" itemprop="articleBody"><details>
|
|||
|
<summary><b>Afficher/cacher Sommaire</b></summary>
|
|||
|
<!-- affichage sommaire -->
|
|||
|
<div class="toc-aside js-toc-root"></div>
|
|||
|
</details><h2 id="guide-dinstallation-nextcloud-17-et-plus-debian--nginx">Guide d’installation Nextcloud 17 et plus (Debian / NGINX)</h2>
|
|||
|
|
|||
|
<p><a href="https://www.c-rieger.de/nextcloud-installation-guide-debian/">Nextcloud 17 installation guide and more (Debian/NGINX)</a> de <a href="https://www.c-rieger.de/author/criegerde/">Carsten Rieger</a> · Publié 2. août 2019 · Mis à jour 30. septembre 2019</p>
|
|||
|
|
|||
|
<p>En suivant ce guide, vous pourrez installer et configurer Nextcloud 17 en fonction de Debian 9.x Stretch ou de Debian 10.x Buster, NGINX 1.17.x, TLSv1.3, PHP 7.3, MariaDB 10.4, Redis, fail2ban, firewall (ufw). ) et obtiendra une note A + de Nextcloud et de Qualys SSL Labs. Nous allons demander et mettre en œuvre votre / vos certificat (s) SSL à partir de Let’s Encrypt. Il vous suffit de modifier les valeurs marquées en rouge ( YOUR.DEDYN.IO , 192.168.2.x , ssh port 22 ) en ce qui concerne votre environnement!</p>
|
|||
|
|
|||
|
<h3 id="pré-requis">Pré-requis</h3>
|
|||
|
|
|||
|
<p>De mon point de vue, les exigences de ce guide peuvent être considérées comme faibles: il suffit de</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>fournir un serveur 64 bits (par exemple, Intel NUC),</li>
|
|||
|
<li>Transférez deux ports (80 et 443) depuis Internet (votre routeur, par exemple FritzBox ou Speedport) vers votre serveur interne Nextcloud</li>
|
|||
|
<li>et installez le système d’exploitation Debian Stretch 9.x (64Bit).</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h2 id="1-installez-nginx">1. Installez NGINX</h2>
|
|||
|
|
|||
|
<p>Préparez votre serveur pour l’installation elle-même:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>su -
|
|||
|
(ou sudo -s)
|
|||
|
|
|||
|
apt install curl gnupg2 git lsb-release ssl-cert ca-certificates apt-transport-https tree locate software-properties-common dirmngr screen htop net-tools zip unzip curl ffmpeg ghostscript libfile-fcntllock-perl -y
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ajouter de nouveaux référentiels de logiciels</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd /etc/apt/sources.list.d
|
|||
|
|
|||
|
echo "deb [arch=amd64] http://nginx.org/packages/mainline/debian $(lsb_release -cs) nginx" | tee nginx.list
|
|||
|
echo "deb [arch=amd64] https://packages.sury.org/php/ $(lsb_release -cs) main" | tee php.list
|
|||
|
echo "deb [arch=amd64] http://mirror2.hs-esslingen.de/mariadb/repo/10.4/debian $(lsb_release -cs) main" | tee mariadb.list
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Téléchargez les clés requises pour faire confiance à toutes les nouvelles sources:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo apt-key add -
|
|||
|
wget -q https://packages.sury.org/php/apt.gpg -O- | apt-key add -
|
|||
|
apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 0xF1656F24C74CD1D8
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Mettez à jour votre serveur, générez des certificats auto-signés et installez nginx:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt update && apt upgrade -y && apt install ssl-cert -y && make-ssl-cert generate-default-snakeoil
|
|||
|
apt remove nginx nginx-extras nginx-common nginx-full -y --allow-change-held-packages
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Assurez-vous qu’Apache (2) ne fonctionne pas, sinon NGINX ne démarrera pas car le port requis (: 80) serait utilisé par Apache (2):</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl stop apache2.service && systemctl disable apache2.service
|
|||
|
apt install nginx -y && systemctl enable nginx.service
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="changer-la-configuration-de-nginx">Changer la configuration de NGINX</h3>
|
|||
|
|
|||
|
<p>Attention remplacer 192.168.2.0/24 et 192.168.2.1 apr vote ip/24 et gateway</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak && vi /etc/nginx/nginx.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Collez les lignes suivantes:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>user www-data;
|
|||
|
worker_processes auto;
|
|||
|
pid /var/run/nginx.pid;
|
|||
|
events {
|
|||
|
worker_connections 1024;
|
|||
|
multi_accept on;
|
|||
|
use epoll;
|
|||
|
}
|
|||
|
http {
|
|||
|
server_names_hash_bucket_size 64;
|
|||
|
upstream php-handler {
|
|||
|
server unix:/run/php/php7.3-fpm.sock;
|
|||
|
}
|
|||
|
set_real_ip_from 127.0.0.1;
|
|||
|
set_real_ip_from 192.168.2.0/24;
|
|||
|
real_ip_header X-Forwarded-For;
|
|||
|
real_ip_recursive on;
|
|||
|
include /etc/nginx/mime.types;
|
|||
|
#include /etc/nginx/proxy.conf;
|
|||
|
#include /etc/nginx/ssl.conf;
|
|||
|
#include /etc/nginx/header.conf;
|
|||
|
#include /etc/nginx/optimization.conf;
|
|||
|
default_type application/octet-stream;
|
|||
|
access_log /var/log/nginx/access.log;
|
|||
|
error_log /var/log/nginx/error.log warn;
|
|||
|
sendfile on;
|
|||
|
send_timeout 3600;
|
|||
|
tcp_nopush on;
|
|||
|
tcp_nodelay on;
|
|||
|
open_file_cache max=500 inactive=10m;
|
|||
|
open_file_cache_errors on;
|
|||
|
keepalive_timeout 65;
|
|||
|
reset_timedout_connection on;
|
|||
|
server_tokens off;
|
|||
|
resolver 192.168.2.1 valid=30s;
|
|||
|
#resolver 127.0.0.53 valid=30s; is recommended but reuqires a valid resolver configuration
|
|||
|
resolver_timeout 5s;
|
|||
|
include /etc/nginx/conf.d/*.conf;
|
|||
|
}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="redémarrez-nginx">Redémarrez NGINX</h3>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>service nginx restart
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Créer des dossiers et appliquer des autorisations</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir -p /var/nc_data /var/www/letsencrypt
|
|||
|
chown -R www-data:www-data /var/nc_data /var/www
|
|||
|
chown -R www-data:root
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="2-installez-php">2. Installez PHP</h2>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt install php7.3-fpm php7.3-gd php7.3-mysql php7.3-curl php7.3-xml php7.3-zip php7.3-intl php7.3-mbstring php7.3-json php7.3-bz2 php7.3-ldap php-apcu imagemagick php-imagick -y
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Génial, PHP 7.3 est déjà installé. Vérifiez vos paramètres de fuseau horaire</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>date
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>et si nécessaire le régler correctement</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>timedatectl set-timezone Europe/Paris
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Configurer PHP</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cp /etc/php/7.3/fpm/pool.d/www.conf /etc/php/7.3/fpm/pool.d/www.conf.bak
|
|||
|
cp /etc/php/7.3/cli/php.ini /etc/php/7.3/cli/php.ini.bak
|
|||
|
cp /etc/php/7.3/fpm/php.ini /etc/php/7.3/fpm/php.ini.bak
|
|||
|
cp /etc/php/7.3/fpm/php-fpm.conf /etc/php/7.3/fpm/php-fpm.conf.bak
|
|||
|
|
|||
|
sed -i "s/;env\[HOSTNAME\] = /env[HOSTNAME] = /" /etc/php/7.3/fpm/pool.d/www.conf
|
|||
|
sed -i "s/;env\[TMP\] = /env[TMP] = /" /etc/php/7.3/fpm/pool.d/www.conf
|
|||
|
sed -i "s/;env\[TMPDIR\] = /env[TMPDIR] = /" /etc/php/7.3/fpm/pool.d/www.conf
|
|||
|
sed -i "s/;env\[TEMP\] = /env[TEMP] = /" /etc/php/7.3/fpm/pool.d/www.conf
|
|||
|
sed -i "s/;env\[PATH\] = /env[PATH] = /" /etc/php/7.3/fpm/pool.d/www.conf
|
|||
|
sed -i "s/pm.max_children = .*/pm.max_children = 240/" /etc/php/7.3/fpm/pool.d/www.conf
|
|||
|
sed -i "s/pm.start_servers = .*/pm.start_servers = 20/" /etc/php/7.3/fpm/pool.d/www.conf
|
|||
|
sed -i "s/pm.min_spare_servers = .*/pm.min_spare_servers = 10/" /etc/php/7.3/fpm/pool.d/www.conf
|
|||
|
sed -i "s/pm.max_spare_servers = .*/pm.max_spare_servers = 20/" /etc/php/7.3/fpm/pool.d/www.conf
|
|||
|
sed -i "s/;pm.max_requests = 500/pm.max_requests = 500/" /etc/php/7.3/fpm/pool.d/www.conf
|
|||
|
|
|||
|
sed -i "s/output_buffering =.*/output_buffering = 'Off'/" /etc/php/7.3/cli/php.ini
|
|||
|
sed -i "s/max_execution_time =.*/max_execution_time = 1800/" /etc/php/7.3/cli/php.ini
|
|||
|
sed -i "s/max_input_time =.*/max_input_time = 3600/" /etc/php/7.3/cli/php.ini
|
|||
|
sed -i "s/post_max_size =.*/post_max_size = 10240M/" /etc/php/7.3/cli/php.ini
|
|||
|
sed -i "s/upload_max_filesize =.*/upload_max_filesize = 10240M/" /etc/php/7.3/cli/php.ini
|
|||
|
sed -i "s/max_file_uploads =.*/max_file_uploads = 100/" /etc/php/7.3/cli/php.ini
|
|||
|
sed -i "s/;date.timezone.*/date.timezone = Europe\/\Berlin/" /etc/php/7.3/cli/php.ini
|
|||
|
sed -i "s/;session.cookie_secure.*/session.cookie_secure = True/" /etc/php/7.3/cli/php.ini
|
|||
|
|
|||
|
sed -i "s/memory_limit = 128M/memory_limit = 512M/" /etc/php/7.3/fpm/php.ini
|
|||
|
sed -i "s/output_buffering =.*/output_buffering = 'Off'/" /etc/php/7.3/fpm/php.ini
|
|||
|
sed -i "s/max_execution_time =.*/max_execution_time = 1800/" /etc/php/7.3/fpm/php.ini
|
|||
|
sed -i "s/max_input_time =.*/max_input_time = 3600/" /etc/php/7.3/fpm/php.ini
|
|||
|
sed -i "s/post_max_size =.*/post_max_size = 10240M/" /etc/php/7.3/fpm/php.ini
|
|||
|
sed -i "s/upload_max_filesize =.*/upload_max_filesize = 10240M/" /etc/php/7.3/fpm/php.ini
|
|||
|
sed -i "s/max_file_uploads =.*/max_file_uploads = 100/" /etc/php/7.3/fpm/php.ini
|
|||
|
sed -i "s/;date.timezone.*/date.timezone = Europe\/\Berlin/" /etc/php/7.3/fpm/php.ini
|
|||
|
sed -i "s/;session.cookie_secure.*/session.cookie_secure = True/" /etc/php/7.3/fpm/php.ini
|
|||
|
sed -i "s/;opcache.enable=.*/opcache.enable=1/" /etc/php/7.3/fpm/php.ini
|
|||
|
sed -i "s/;opcache.enable_cli=.*/opcache.enable_cli=1/" /etc/php/7.3/fpm/php.ini
|
|||
|
sed -i "s/;opcache.memory_consumption=.*/opcache.memory_consumption=128/" /etc/php/7.3/fpm/php.ini
|
|||
|
sed -i "s/;opcache.interned_strings_buffer=.*/opcache.interned_strings_buffer=8/" /etc/php/7.3/fpm/php.ini
|
|||
|
sed -i "s/;opcache.max_accelerated_files=.*/opcache.max_accelerated_files=10000/" /etc/php/7.3/fpm/php.ini
|
|||
|
sed -i "s/;opcache.revalidate_freq=.*/opcache.revalidate_freq=1/" /etc/php/7.3/fpm/php.ini
|
|||
|
sed -i "s/;opcache.save_comments=.*/opcache.save_comments=1/" /etc/php/7.3/fpm/php.ini
|
|||
|
|
|||
|
sed -i "s/;emergency_restart_threshold =.*/emergency_restart_threshold = 10/" /etc/php/7.3/fpm/php-fpm.conf
|
|||
|
sed -i "s/;emergency_restart_interval =.*/emergency_restart_interval = 1m/" /etc/php/7.3/fpm/php-fpm.conf
|
|||
|
sed -i "s/;process_control_timeout =.*/process_control_timeout = 10s/" /etc/php/7.3/fpm/php-fpm.conf
|
|||
|
|
|||
|
sed -i "s/09,39.*/# &/" /etc/cron.d/php
|
|||
|
(crontab -l ; echo "09,39 * * * * /usr/lib/php/sessionclean 2>&1") | crontab -u root -
|
|||
|
|
|||
|
cp /etc/ImageMagick-6/policy.xml /etc/ImageMagick-6/policy.xml.bak
|
|||
|
sed -i "s/rights\=\"none\" pattern\=\"PS\"/rights\=\"read\|write\" pattern\=\"PS\"/" /etc/ImageMagick-6/policy.xml
|
|||
|
sed -i "s/rights\=\"none\" pattern\=\"EPI\"/rights\=\"read\|write\" pattern\=\"EPI\"/" /etc/ImageMagick-6/policy.xml
|
|||
|
sed -i "s/rights\=\"none\" pattern\=\"PDF\"/rights\=\"read\|write\" pattern\=\"PDF\"/" /etc/ImageMagick-6/policy.xml
|
|||
|
sed -i "s/rights\=\"none\" pattern\=\"XPS\"/rights\=\"read\|write\" pattern\=\"XPS\"/" /etc/ImageMagick-6/policy.xml
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Redémarrez les deux, PHP et NGINX</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>service php7.3-fpm restart && service nginx restart
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="3-installez-mariadb">3. Installez MariaDB</h2>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt update && apt install mariadb-server -y
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérifiez la version de votre serveur de base de données:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mysql --version
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><em>mysql Ver 15.1 Distrib 10.4.x-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2</em> devrait apparaître.</p>
|
|||
|
|
|||
|
<h3 id="mariadb-sécurisé">MariaDB sécurisé</h3>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mysql_secure_installation
|
|||
|
Switch to unix_socket authentication [Y/n] N
|
|||
|
Enter current password for root (enter for none): <ENTER> or type the password Set root password? [Y/n] Y
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><em>Si déjà défini lors de l’installation de MariaDB, il vous sera demandé si vous souhaitez modifier ou conserver le mot de passe.</em></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Remove anonymous users? [Y/n] Y
|
|||
|
Disallow root login remotely? [Y/n] Y
|
|||
|
Remove test database and access to it? [Y/n] Y
|
|||
|
Reload privilege tables now? [Y/n] Y
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="configurer-mariadb">Configurer MariaDB</h3>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>service mysql stop
|
|||
|
mv /etc/mysql/my.cnf /etc/mysql/my.cnf.bak && vi /etc/mysql/my.cnf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Collez les lignes suivantes:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[client]
|
|||
|
default-character-set = utf8mb4
|
|||
|
port = 3306
|
|||
|
socket = /var/run/mysqld/mysqld.sock
|
|||
|
|
|||
|
[mysqld_safe]
|
|||
|
log_error=/var/log/mysql/mysql_error.log
|
|||
|
nice = 0
|
|||
|
socket = /var/run/mysqld/mysqld.sock
|
|||
|
|
|||
|
[mysqld]
|
|||
|
basedir = /usr
|
|||
|
bind-address = 127.0.0.1
|
|||
|
binlog_format = ROW
|
|||
|
bulk_insert_buffer_size = 16M
|
|||
|
character-set-server = utf8mb4
|
|||
|
collation-server = utf8mb4_general_ci
|
|||
|
concurrent_insert = 2
|
|||
|
connect_timeout = 5
|
|||
|
datadir = /var/lib/mysql
|
|||
|
default_storage_engine = InnoDB
|
|||
|
expire_logs_days = 10
|
|||
|
general_log_file = /var/log/mysql/mysql.log
|
|||
|
general_log = 0
|
|||
|
innodb_buffer_pool_size = 1024M
|
|||
|
innodb_buffer_pool_instances = 1
|
|||
|
innodb_flush_log_at_trx_commit = 2
|
|||
|
innodb_log_buffer_size = 32M
|
|||
|
innodb_max_dirty_pages_pct = 90
|
|||
|
innodb_file_per_table = 1
|
|||
|
innodb_open_files = 400
|
|||
|
innodb_io_capacity = 4000
|
|||
|
innodb_flush_method = O_DIRECT
|
|||
|
key_buffer_size = 128M
|
|||
|
lc_messages_dir = /usr/share/mysql
|
|||
|
lc_messages = en_US
|
|||
|
log_bin = /var/log/mysql/mariadb-bin
|
|||
|
log_bin_index = /var/log/mysql/mariadb-bin.index
|
|||
|
log_error=/var/log/mysql/mysql_error.log
|
|||
|
log_slow_verbosity = query_plan
|
|||
|
log_warnings = 2
|
|||
|
long_query_time = 1
|
|||
|
max_allowed_packet = 16M
|
|||
|
max_binlog_size = 100M
|
|||
|
max_connections = 200
|
|||
|
max_heap_table_size = 64M
|
|||
|
myisam_recover_options = BACKUP
|
|||
|
myisam_sort_buffer_size = 512M
|
|||
|
port = 3306
|
|||
|
pid-file = /var/run/mysqld/mysqld.pid
|
|||
|
query_cache_limit = 2M
|
|||
|
query_cache_size = 64M
|
|||
|
query_cache_type = 1
|
|||
|
query_cache_min_res_unit = 2k
|
|||
|
read_buffer_size = 2M
|
|||
|
read_rnd_buffer_size = 1M
|
|||
|
skip-external-locking
|
|||
|
skip-name-resolve
|
|||
|
slow_query_log_file = /var/log/mysql/mariadb-slow.log
|
|||
|
slow-query-log = 1
|
|||
|
socket = /var/run/mysqld/mysqld.sock
|
|||
|
sort_buffer_size = 4M
|
|||
|
table_open_cache = 400
|
|||
|
thread_cache_size = 128
|
|||
|
tmp_table_size = 64M
|
|||
|
tmpdir = /tmp
|
|||
|
transaction_isolation = READ-COMMITTED
|
|||
|
user = mysql
|
|||
|
wait_timeout = 600
|
|||
|
|
|||
|
[mysqldump]
|
|||
|
max_allowed_packet = 16M
|
|||
|
quick
|
|||
|
quote-names
|
|||
|
|
|||
|
[isamchk]
|
|||
|
key_buffer = 16M
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Redémarrez et connectez-vous à MariaDB</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>service mysql restart && mysql -uroot -p
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="créer-base-nextcloud">Créer base nextcloud</h3>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>la base de données <strong>nextcloud</strong></li>
|
|||
|
<li>l’utilisateur <strong>nextcloud</strong></li>
|
|||
|
<li>et son mot de passe <strong>password</strong></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>CREATE DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; CREATE USER nextcloud@localhost identified by 'password'; GRANT ALL PRIVILEGES on nextcloud.* to nextcloud@localhost; FLUSH privileges; quit;
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérifiez que le niveau d’isolement de la transaction a été défini sur READ_Commit et que le classement a été défini sur UTF8MB4 correctement:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mysql -h localhost -uroot -p -e "SELECT @@TX_ISOLATION; SELECT SCHEMA_NAME 'database', default_character_set_name 'charset', DEFAULT_COLLATION_NAME 'collation' FROM information_schema.SCHEMATA WHERE SCHEMA_NAME='nextcloud'"
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Si le résultat est “READ-COMMITTED” et “utf8mb4_general_ci” comme indiqué, poursuivez l’installation de redis.</p>
|
|||
|
|
|||
|
<h2 id="4-redis">4. Redis</h2>
|
|||
|
|
|||
|
<p><em>Redis, qui signifie Remote Dictionary Server (Serveur de dictionnaire à distance), est un système de stockage de données clé-valeur en mémoire, open source et rapide, pour une utilisation en tant que base de données, de cache, de courtier de messages et de file d’attente. Le projet a démarré lorsque Salvatore Sanfilippo, le développeur initial de Redis, a essayé d’améliorer la scalabilité de sa startup italienne. Redis offre désormais des temps de réponse inférieurs à la milliseconde permettant des millions de demandes par seconde pour des applications en temps réel dans les domaines du jeu, de la technologie publicitaire, des services financiers, des soins de santé et de l’Internet des objets. Redis est un choix populaire pour la mise en cache, la gestion de session, les jeux, les classements, l’analyse en temps réel, le géospatial, l’appel de voiture avec chauffeur, le chat/la messagerie, le streaming multimédia et les applications pub/sub.</em></p>
|
|||
|
|
|||
|
<p>Installation</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt update && apt install redis-server php-redis -y
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Changer la configuration et l’appartenance à un groupe</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cp /etc/redis/redis.conf /etc/redis/redis.conf.bak
|
|||
|
sed -i "s/port 6379/port 0/" /etc/redis/redis.conf
|
|||
|
sed -i s/\#\ unixsocket/\unixsocket/g /etc/redis/redis.conf
|
|||
|
sed -i "s/unixsocketperm 700/unixsocketperm 770/" /etc/redis/redis.conf
|
|||
|
sed -i "s/# maxclients 10000/maxclients 512/" /etc/redis/redis.conf
|
|||
|
usermod -a -G redis www-data
|
|||
|
|
|||
|
cp /etc/sysctl.conf /etc/sysctl.conf.bak
|
|||
|
sed -i '$avm.overcommit_memory = 1' /etc/sysctl.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Il est recommandé de redémarrer votre serveur une fois:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>shutdown -r now
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="5-nextcloud">5. Nextcloud</h2>
|
|||
|
|
|||
|
<p>Créez les fichiers de configuration, commencez par <strong>/etc/nginx/conf.d/nextcloud.conf</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>su -
|
|||
|
[ -f /etc/nginx/conf.d/default.conf ] && mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak
|
|||
|
touch /etc/nginx/conf.d/default.conf
|
|||
|
nano /etc/nginx/conf.d/nextcloud.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>ATTENTION remplacer <strong>your.dedyn.io</strong> par votre domaine<br />
|
|||
|
Collez les lignes suivantes:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
|
|||
|
server_name your.dedyn.io;
|
|||
|
listen 80 default_server;
|
|||
|
listen [::]:80 default_server;
|
|||
|
location ^~ /.well-known/acme-challenge {
|
|||
|
proxy_pass http://127.0.0.1:81;
|
|||
|
proxy_set_header Host $host;
|
|||
|
}
|
|||
|
location / {
|
|||
|
return 301 https://$host$request_uri;
|
|||
|
}
|
|||
|
}
|
|||
|
server {
|
|||
|
server_name your.dedyn.io;
|
|||
|
listen 443 ssl http2 default_server;
|
|||
|
listen [::]:443 ssl http2 default_server;
|
|||
|
root /var/www/nextcloud/;
|
|||
|
location = /robots.txt {
|
|||
|
allow all;
|
|||
|
log_not_found off;
|
|||
|
access_log off;
|
|||
|
}
|
|||
|
location = /.well-known/carddav {
|
|||
|
return 301 $scheme://$host/remote.php/dav;
|
|||
|
}
|
|||
|
location = /.well-known/caldav {
|
|||
|
return 301 $scheme://$host/remote.php/dav;
|
|||
|
}
|
|||
|
#SOCIAL app enabled? Please uncomment the following row
|
|||
|
#rewrite ^/.well-known/webfinger /public.php?service=webfinger last;
|
|||
|
#WEBFINGER app enabled? Please uncomment the following two rows.
|
|||
|
#rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
|
|||
|
#rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
|
|||
|
client_max_body_size 10240M;
|
|||
|
location / {
|
|||
|
rewrite ^ /index.php$request_uri;
|
|||
|
}
|
|||
|
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
|
|||
|
deny all;
|
|||
|
}
|
|||
|
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
|
|||
|
deny all;
|
|||
|
}
|
|||
|
location ^~ /apps/rainloop/app/data {
|
|||
|
deny all;
|
|||
|
}
|
|||
|
location ~ \.(?:flv|mp4|mov|m4a)$ {
|
|||
|
mp4;
|
|||
|
mp4_buffer_size 100M;
|
|||
|
mp4_max_buffer_size 1024M;
|
|||
|
fastcgi_split_path_info ^(.+?.php)(\/.*|)$;
|
|||
|
include fastcgi_params;
|
|||
|
include php_optimization.conf;
|
|||
|
fastcgi_pass php-handler;
|
|||
|
fastcgi_param HTTPS on;
|
|||
|
}
|
|||
|
location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+).php(?:$|\/) {
|
|||
|
fastcgi_split_path_info ^(.+?.php)(\/.*|)$;
|
|||
|
include fastcgi_params;
|
|||
|
include php_optimization.conf;
|
|||
|
fastcgi_pass php-handler;
|
|||
|
fastcgi_param HTTPS on;
|
|||
|
}
|
|||
|
location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
|
|||
|
try_files $uri/ =404;
|
|||
|
index index.php;
|
|||
|
}
|
|||
|
location ~ .(?:css|js|woff2?|svg|gif|map|png|html|ttf|ico|jpg|jpeg)$ {
|
|||
|
try_files $uri /index.php$request_uri;
|
|||
|
access_log off;
|
|||
|
expires 360d;
|
|||
|
}
|
|||
|
}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Si vous souhaitez que votre Nextcloud s’exécute dans un sous-répertoire (sous-dossier) comme https://your.dedyn.io/ nextcloud, utilisez plutôt nextcloud.conf:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
|
|||
|
server_name your.dedyn.io;
|
|||
|
listen 80 default_server;
|
|||
|
listen [::]:80 default_server;
|
|||
|
location ^~ /.well-known/acme-challenge {
|
|||
|
proxy_pass http://127.0.0.1:81;
|
|||
|
proxy_set_header Host $host;
|
|||
|
}
|
|||
|
location / {
|
|||
|
return 301 https://$host$request_uri;
|
|||
|
}
|
|||
|
}
|
|||
|
server {
|
|||
|
server_name your.dedyn.io;
|
|||
|
listen 443 ssl http2 default_server;
|
|||
|
listen [::]:443 ssl http2 default_server;
|
|||
|
root /var/www/;
|
|||
|
location = /robots.txt {
|
|||
|
allow all;
|
|||
|
log_not_found off;
|
|||
|
access_log off;
|
|||
|
}
|
|||
|
location = /.well-known/carddav {
|
|||
|
return 301 $scheme://$host/nextcloud/remote.php/dav;
|
|||
|
}
|
|||
|
location = /.well-known/caldav {
|
|||
|
return 301 $scheme://$host/nextcloud/remote.php/dav;
|
|||
|
}
|
|||
|
#SOCIAL app enabled? Please uncomment the following row
|
|||
|
#rewrite ^/.well-known/webfinger /nextcloud/public.php?service=webfinger last;
|
|||
|
#WEBFINGER app enabled? Please uncomment the following two rows.
|
|||
|
#rewrite ^/.well-known/host-meta /nextcloud/public.php?service=host-meta last;
|
|||
|
#rewrite ^/.well-known/host-meta.json /nextcloud/public.php?service=host-meta-json last;
|
|||
|
client_max_body_size 10240M;
|
|||
|
location /nextcloud {
|
|||
|
rewrite ^ /nextcloud/index.php$request_uri;
|
|||
|
}
|
|||
|
location ~ ^/nextcloud/(?:build|tests|config|lib|3rdparty|templates|data)/ {
|
|||
|
deny all;
|
|||
|
}
|
|||
|
location ~ ^/nextcloud/(?:\.|autotest|occ|issue|indie|db_|console) {
|
|||
|
deny all;
|
|||
|
}
|
|||
|
location ^~ /nextcloud/apps/rainloop/app/data {
|
|||
|
deny all;
|
|||
|
}
|
|||
|
location ~ \.(?:flv|mp4|mov|m4a)$ {
|
|||
|
mp4;
|
|||
|
mp4_buffer_size 100M;
|
|||
|
mp4_max_buffer_size 1024M;
|
|||
|
fastcgi_split_path_info ^(.+?.php)(\/.*|)$;
|
|||
|
include fastcgi_params;
|
|||
|
include php_optimization.conf;
|
|||
|
fastcgi_pass php-handler;
|
|||
|
fastcgi_param HTTPS on;
|
|||
|
}
|
|||
|
location ~ ^\/nextcloud/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+).php(?:$|\/) {
|
|||
|
fastcgi_split_path_info ^(.+?.php)(\/.*|)$;
|
|||
|
include fastcgi_params;
|
|||
|
include php_optimization.conf;
|
|||
|
fastcgi_pass php-handler;
|
|||
|
fastcgi_param HTTPS on;
|
|||
|
}
|
|||
|
location ~ ^\/nextcloud/(?:updater|oc[ms]-provider)(?:$|\/) {
|
|||
|
try_files $uri/ =404;
|
|||
|
index index.php;
|
|||
|
}
|
|||
|
location ~ .(?:css|js|woff2?|svg|gif|map|png|html|ttf|ico|jpg|jpeg)$ {
|
|||
|
try_files $uri /nextcloud/index.php$request_uri;
|
|||
|
access_log off;
|
|||
|
expires 360d;
|
|||
|
}
|
|||
|
}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Créer le letsencrypt.conf</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/nginx/conf.d/letsencrypt.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Collez les lignes suivantes:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
|
|||
|
server_name 127.0.0.1;
|
|||
|
listen 127.0.0.1:81 default_server;
|
|||
|
charset utf-8;
|
|||
|
location ^~ /.well-known/acme-challenge {
|
|||
|
default_type text/plain;
|
|||
|
root /var/www/letsencrypt;
|
|||
|
}
|
|||
|
}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Créer le fichier ssl.conf</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/nginx/ssl.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Coller les lignes suivantes</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
|
|||
|
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
|
|||
|
ssl_trusted_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
|
|||
|
#ssl_certificate /etc/letsencrypt/rsa-certs/fullchain.pem;
|
|||
|
#ssl_certificate_key /etc/letsencrypt/rsa-certs/privkey.pem;
|
|||
|
#ssl_certificate /etc/letsencrypt/ecc-certs/fullchain.pem;
|
|||
|
#ssl_certificate_key /etc/letsencrypt/ecc-certs/privkey.pem;
|
|||
|
#ssl_trusted_certificate /etc/letsencrypt/ecc-certs/chain.pem;
|
|||
|
ssl_dhparam /etc/ssl/certs/dhparam.pem;
|
|||
|
ssl_session_timeout 1d;
|
|||
|
ssl_session_cache shared:SSL:50m;
|
|||
|
ssl_session_tickets off;
|
|||
|
ssl_protocols TLSv1.3 TLSv1.2;
|
|||
|
ssl_ciphers 'TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384';
|
|||
|
ssl_ecdh_curve X448:secp521r1:secp384r1:prime256v1;
|
|||
|
ssl_prefer_server_ciphers on;
|
|||
|
ssl_stapling on;
|
|||
|
ssl_stapling_verify on;
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Créer le proxy.conf</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/nginx/proxy.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Coller les lignes suivantes</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>proxy_set_header Host $host;
|
|||
|
proxy_set_header X-Real-IP $remote_addr;
|
|||
|
proxy_set_header X-Forwarded-Host $host;
|
|||
|
proxy_set_header X-Forwarded-Protocol $scheme;
|
|||
|
proxy_set_header X-Forwarded-For $remote_addr;
|
|||
|
proxy_set_header X-Forwarded-Port $server_port;
|
|||
|
proxy_set_header X-Forwarded-Server $host;
|
|||
|
proxy_connect_timeout 3600;
|
|||
|
proxy_send_timeout 3600;
|
|||
|
proxy_read_timeout 3600;
|
|||
|
proxy_redirect off;
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Créer le header.conf</p>
|
|||
|
|
|||
|
<p>vi /etc/nginx/header.conf</p>
|
|||
|
|
|||
|
<p>Coller les lignes suivantes</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
|
|||
|
add_header X-Robots-Tag none;
|
|||
|
add_header X-Download-Options noopen;
|
|||
|
add_header X-Permitted-Cross-Domain-Policies none;
|
|||
|
add_header X-Content-Type-Options "nosniff" always;
|
|||
|
add_header X-XSS-Protection "1; mode=block" always;
|
|||
|
add_header Referrer-Policy "no-referrer" always;
|
|||
|
#add_header Feature-Policy "accelerometer 'none'; autoplay 'self'; geolocation 'none'; midi 'none'; sync-xhr 'self' ; microphone 'self'; camera 'self'; magnetometer 'none'; gyroscope 'none'; speaker 'self'; fullscreen 'self'; payment 'none'; usb 'none'";
|
|||
|
add_header X-Frame-Options "SAMEORIGIN";
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Créer optimization.conf</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/nginx/optimization.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Coller les lignes suivantes</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>fastcgi_hide_header X-Powered-By;
|
|||
|
fastcgi_read_timeout 3600;
|
|||
|
fastcgi_send_timeout 3600;
|
|||
|
fastcgi_connect_timeout 3600;
|
|||
|
fastcgi_buffers 64 64K;
|
|||
|
fastcgi_buffer_size 256k;
|
|||
|
fastcgi_busy_buffers_size 3840K;
|
|||
|
fastcgi_cache_key $http_cookie$request_method$host$request_uri;
|
|||
|
fastcgi_cache_use_stale error timeout invalid_header http_500;
|
|||
|
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
|
|||
|
gzip on;
|
|||
|
gzip_vary on;
|
|||
|
gzip_comp_level 4;
|
|||
|
gzip_min_length 256;
|
|||
|
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
|
|||
|
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
|
|||
|
gzip_disable "MSIE [1-6]\.";
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Créez le php_optimization.conf</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/nginx/php_optimization.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Coller les lignes suivantes</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
|||
|
fastcgi_param PATH_INFO $fastcgi_path_info;
|
|||
|
fastcgi_param modHeadersAvailable true;
|
|||
|
fastcgi_param front_controller_active true;
|
|||
|
fastcgi_intercept_errors on;
|
|||
|
fastcgi_request_buffering off;
|
|||
|
fastcgi_cache_valid 404 1m;
|
|||
|
fastcgi_cache_valid any 1h;
|
|||
|
fastcgi_cache_methods GET HEAD;
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="améliorer-la-sécurité">Améliorer la sécurité</h3>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>S’il vous plaît soyez patient, cela prendra un certain temps en fonction de votre matériel.</p>
|
|||
|
|
|||
|
<h3 id="redémarrez-nginx-1">Redémarrez NGINX</h3>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sed -i s/\#\include/\include/g /etc/nginx/nginx.conf && service nginx restart
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="téléchargez-et-extrayez-le-logiciel-nextcloud-puis-demandez-vos-certificats-ssl-à-lets-encrypt-via-acme">Téléchargez et extrayez le logiciel Nextcloud, puis demandez vos certificats SSL à Let’s Encrypt via acme:</h3>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd /usr/local/src
|
|||
|
wget https://download.nextcloud.com/server/releases/latest.tar.bz2
|
|||
|
tar -xjf latest.tar.bz2 -C /var/www && chown -R www-data:www-data /var/www/ && rm -f latest.tar.bz2
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Créez un utilisateur technique pour installer et renouveler vos certificats SSL</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>adduser acmeuser
|
|||
|
usermod -a -G www-data acmeuser
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Problème visudo</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>visudo
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>et ajoutez la ligne suivante à la fin du fichier</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>acmeuser ALL=NOPASSWD: /bin/systemctl reload nginx.service
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>par exemple, redémarrer nginx sans mot de passe.</p>
|
|||
|
|
|||
|
<h3 id="pour-demander-des-certificats-ssl-à-letsencrypt-il-suffit-dinstaller-acme-et-de-demander-votre--vos-certificat-s-ssl">Pour demander des certificats SSL à letsencrypt, il suffit d’installer acme et de demander votre / vos certificat (s) SSL:</h3>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>su - acmeuser
|
|||
|
curl https://get.acme.sh | sh
|
|||
|
exit
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="créez-trois-dossiers-pour-demander-et-stocker-vos-certificats-ssl-à-remplacez-votrededynio">Créez trois dossiers pour demander et stocker vos certificats SSL à (remplacez votre.dedyn.io):</h3>
|
|||
|
|
|||
|
<p>Attention , remplacer <strong>your.dedyn.io</strong> par votre domaine</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
|
|||
|
mkdir -p /var/www/letsencrypt/.well-known/acme-challenge /etc/letsencrypt/rsa-certs /etc/letsencrypt/ecc-certs
|
|||
|
chmod -R 775 /var/www/letsencrypt /etc/letsencrypt && chown -R www-data:www-data /var/www/ /etc/letsencrypt
|
|||
|
su - acmeuser
|
|||
|
acme.sh --issue -d your.dedyn.io --keylength 4096 -w /var/www/letsencrypt --key-file /etc/letsencrypt/rsa-certs/privkey.pem --ca-file /etc/letsencrypt/rsa-certs/chain.pem --cert-file /etc/letsencrypt/rsa-certs/cert.pem --fullchain-file /etc/letsencrypt/rsa-certs/fullchain.pem
|
|||
|
acme.sh --issue -d your.dedyn.io --keylength ec-384 -w /var/www/letsencrypt --key-file /etc/letsencrypt/ecc-certs/privkey.pem --ca-file /etc/letsencrypt/ecc-certs/chain.pem --cert-file /etc/letsencrypt/ecc-certs/cert.pem --fullchain-file /etc/letsencrypt/ecc-certs/fullchain.pem
|
|||
|
exit
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="appliquez-les-autorisations-à-laide-dun-script-permissionssh-">Appliquez les autorisations à l’aide d’un script permissions.sh :</h3>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /root/permissions.sh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Collez les lignes suivantes:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#!/bin/bash
|
|||
|
find /var/www/ -type f -print0 | xargs -0 chmod 0640
|
|||
|
find /var/www/ -type d -print0 | xargs -0 chmod 0750
|
|||
|
chown -R www-data:www-data /var/www/
|
|||
|
chown -R www-data:www-data /var/nc_data/
|
|||
|
chmod 0644 /var/www/nextcloud/.htaccess
|
|||
|
chmod 0644 /var/www/nextcloud/.user.ini
|
|||
|
chmod 600 /etc/letsencrypt/rsa-certs/fullchain.pem
|
|||
|
chmod 600 /etc/letsencrypt/rsa-certs/privkey.pem
|
|||
|
chmod 600 /etc/letsencrypt/rsa-certs/chain.pem
|
|||
|
chmod 600 /etc/letsencrypt/rsa-certs/cert.pem
|
|||
|
chmod 600 /etc/letsencrypt/ecc-certs/fullchain.pem
|
|||
|
chmod 600 /etc/letsencrypt/ecc-certs/privkey.pem
|
|||
|
chmod 600 /etc/letsencrypt/ecc-certs/chain.pem
|
|||
|
chmod 600 /etc/letsencrypt/ecc-certs/cert.pem
|
|||
|
chmod 600 /etc/ssl/certs/dhparam.pem
|
|||
|
exit 0
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Exécutez le script:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chmod +x /root/permissions.sh && /root/permissions.sh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Modifiez le fichier ssl.conf et redémarrez NGINX:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sed -i '/ssl-cert-snakeoil/d' /etc/nginx/ssl.conf
|
|||
|
sed -i s/\#\ssl/\ssl/g /etc/nginx/ssl.conf
|
|||
|
service nginx restart
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Installez Nextcloud en mode silencieux</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>su - www-data -s /bin/bash -c 'php /var/www/nextcloud/occ maintenance:install --database "mysql" --database-name "nextcloud" --database-user "nextcloud" --database-pass "nextcloud" --admin-user "YourNextcloudAdmin" --admin-pass "YourNextcloudAdminPasssword" --data-dir "/var/nc_data"'
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Information</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>–Database-name “ nextcloud ”: comme défini ci-dessus lors de la création de la base de données</li>
|
|||
|
<li>–Database-user “ nextcloud ”: comme défini ci-dessus lors de la création de l’utilisateur de la base de données</li>
|
|||
|
<li>–Database-pass “ nextcloud ”: comme défini ci-dessus lors de la création du mot de passe de l’utilisateur</li>
|
|||
|
<li>–Admin-user “ YourNextcloudAdmin ”: votre libre choix</li>
|
|||
|
<li>–Admin-pass “ YourNextcloudAdminPasssword ”: votre libre choix</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>su - www-data -s /bin/bash -c 'php /var/www/nextcloud/occ config:system:set trusted_domains 0 --value=your.dedyn.io'
|
|||
|
su - www-data -s /bin/bash -c 'php /var/www/nextcloud/occ config:system:set overwrite.cli.url --value=https://your.dedyn.io'
|
|||
|
cp /var/www/nextcloud/config/config.php /var/www/nextcloud/config/config.php.bak
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Développez votre fichier Nextcloud config.php:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sed -i 's/^[ ]*//' /var/www/nextcloud/config/config.php
|
|||
|
sed -i '/);/d' /var/www/nextcloud/config/config.php
|
|||
|
|
|||
|
cat <<EOF >>/var/www/nextcloud/config/config.php
|
|||
|
'activity_expire_days' => 14,
|
|||
|
'auth.bruteforce.protection.enabled' => true,
|
|||
|
'blacklisted_files' =>
|
|||
|
array (
|
|||
|
0 => '.htaccess',
|
|||
|
1 => 'Thumbs.db',
|
|||
|
2 => 'thumbs.db',
|
|||
|
),
|
|||
|
'cron_log' => true,
|
|||
|
'enable_previews' => true,
|
|||
|
'enabledPreviewProviders' =>
|
|||
|
array (
|
|||
|
0 => 'OC\\Preview\\PNG',
|
|||
|
1 => 'OC\\Preview\\JPEG',
|
|||
|
2 => 'OC\\Preview\\GIF',
|
|||
|
3 => 'OC\\Preview\\BMP',
|
|||
|
4 => 'OC\\Preview\\XBitmap',
|
|||
|
5 => 'OC\\Preview\\Movie',
|
|||
|
6 => 'OC\\Preview\\PDF',
|
|||
|
7 => 'OC\\Preview\\MP3',
|
|||
|
8 => 'OC\\Preview\\TXT',
|
|||
|
9 => 'OC\\Preview\\MarkDown',
|
|||
|
),
|
|||
|
'filesystem_check_changes' => 0,
|
|||
|
'filelocking.enabled' => 'true',
|
|||
|
'htaccess.RewriteBase' => '/',
|
|||
|
'integrity.check.disabled' => false,
|
|||
|
'knowledgebaseenabled' => false,
|
|||
|
'logfile' => '/var/nc_data/nextcloud.log',
|
|||
|
'loglevel' => 2,
|
|||
|
'logtimezone' => 'Europe/Berlin',
|
|||
|
'log_rotate_size' => 104857600,
|
|||
|
'maintenance' => false,
|
|||
|
'memcache.local' => '\\OC\\Memcache\\APCu',
|
|||
|
'memcache.locking' => '\\OC\\Memcache\\Redis',
|
|||
|
'overwriteprotocol' => 'https',
|
|||
|
'preview_max_x' => 1024,
|
|||
|
'preview_max_y' => 768,
|
|||
|
'preview_max_scale_factor' => 1,
|
|||
|
'redis' =>
|
|||
|
array (
|
|||
|
'host' => '/var/run/redis/redis-server.sock',
|
|||
|
# ATTENTION if you operate on Debian 9.x:
|
|||
|
# 'host' => '/var/run/redis/redis.sock',
|
|||
|
'port' => 0,
|
|||
|
'timeout' => 0.0,
|
|||
|
),
|
|||
|
'quota_include_external_storage' => false,
|
|||
|
'share_folder' => '/Shares',
|
|||
|
'skeletondirectory' => '',
|
|||
|
'theme' => '',
|
|||
|
'trashbin_retention_obligation' => 'auto, 7',
|
|||
|
'updater.release.channel' => 'stable',
|
|||
|
);
|
|||
|
EOF
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="editer-le-nextcloud-userini">Editer le Nextcloud .user.ini</h3>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -u www-data sed -i "s/output_buffering=.*/output_buffering='Off'/" /var/www/nextcloud/.user.ini
|
|||
|
service php7.3-fpm restart && service redis-server restart && service nginx restart
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="ajuster-les-applications-nextcloud">Ajuster les applications Nextcloud</h3>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>su - www-data -s /bin/bash -c 'php /var/www/nextcloud/occ app:disable survey_client'
|
|||
|
su - www-data -s /bin/bash -c 'php /var/www/nextcloud/occ app:disable firstrunwizard'
|
|||
|
su - www-data -s /bin/bash -c 'php /var/www/nextcloud/occ app:enable admin_audit'
|
|||
|
su - www-data -s /bin/bash -c 'php /var/www/nextcloud/occ app:enable files_pdfviewer'
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Optimisez votre Nextcloud avec deux scripts shell</p>
|
|||
|
|
|||
|
<p>(a) mettre à jour votre environnement périodiquement <a href="https://github.com/criegerde/install-nextcloud/blob/master/maintenance/debian/upgrade-debian.sh">upgrade.sh</a></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /root/upgrade.sh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Debian 9.x 10.x
|
|||
|
#!/bin/bash
|
|||
|
/usr/sbin/service nginx stop
|
|||
|
su - www-data -s /bin/bash -c 'php /var/www/nextcloud/updater/updater.phar'
|
|||
|
su - www-data -s /bin/bash -c 'php /var/www/nextcloud/occ status'
|
|||
|
su - www-data -s /bin/bash -c 'php /var/www/nextcloud/occ -V'
|
|||
|
su - www-data -s /bin/bash -c 'php /var/www/nextcloud/occ db:add-missing-indices'
|
|||
|
su - www-data -s /bin/bash -c 'php /var/www/nextcloud/occ db:convert-filecache-bigint'
|
|||
|
sed -i "s/output_buffering=.*/output_buffering='Off'/" /var/www/nextcloud/.user.ini
|
|||
|
chown -R www-data:www-data /var/www/nextcloud
|
|||
|
su - www-data -s /bin/bash -c 'php /var/www/nextcloud/occ app:update --all'
|
|||
|
/usr/sbin/service php7.3-fpm restart
|
|||
|
/usr/sbin/service nginx restart
|
|||
|
exit 0
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>(infos: <a href="https://docs.nextcloud.com/server/15/admin_manual/configuration_database/bigint_identifiers.html">BigInt</a> , <a href="https://docs.nextcloud.com/server/15/admin_manual/configuration_server/occ_command.html?highlight=add%20missing%20indices#add-missing-indices">indices manquants</a> )</p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<p>(b) optimisez périodiquement votre Nextcloud <a href="https://github.com/criegerde/install-nextcloud/blob/master/maintenance/debian/optimize-debian.sh">Texte du lien</a></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nan /root/optimize.sh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#!/bin/bash
|
|||
|
# ATTENTION if you operate on Debian 9.x:
|
|||
|
# redis-cli -s /var/run/redis/redis.sock <<EOF
|
|||
|
redis-cli -s /var/run/redis/redis-server.sock <<EOF
|
|||
|
FLUSHALL
|
|||
|
quit
|
|||
|
EOF
|
|||
|
su - www-data -s /bin/bash -c 'php /var/www/nextcloud/occ files:scan --all'
|
|||
|
su - www-data -s /bin/bash -c 'php /var/www/nextcloud/occ files:scan-app-data'
|
|||
|
exit 0
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Sauvegarder les deux scripts et les marquer comme exécutables</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chmod +x /root/*.sh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Émettez les deux fois:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/root/upgrade.sh && /root/optimize.sh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ajouter des tâches cron pour Nextcloud pour www-data et root</p>
|
|||
|
|
|||
|
<p>Pour www-data :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>crontab -u www-data -e
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Coller les lignes suivantes</p>
|
|||
|
|
|||
|
<p><code class="language-plaintext highlighter-rouge">*/5 * * * * php -f /var/www/nextcloud/cron.php > /dev/null 2>&1</code></p>
|
|||
|
|
|||
|
<p>Pour root :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>crontab -e
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Collez les lignes suivantes:</p>
|
|||
|
|
|||
|
<p><code class="language-plaintext highlighter-rouge">5 1 * * * /root/optimize.sh 2>&1</code></p>
|
|||
|
|
|||
|
<h3 id="basculez-nextcloud-pour-utiliser-cronphp">Basculez Nextcloud pour utiliser cron.php</h3>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>su - www-data -s /bin/bash -c 'php /var/www/nextcloud/occ background:cron'
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="redémarrer-tous-les-services">Redémarrer tous les services</h3>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>service mysql restart && service php7.3-fpm restart && service redis-server restart && service nginx restart
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="connectez-vous-à-votre-tout-nouveau-nextcloud-dans-votre-navigateur">Connectez-vous à votre tout nouveau Nextcloud dans votre navigateur</h3>
|
|||
|
|
|||
|
<p>https://your.dedyn.io/login</p>
|
|||
|
|
|||
|
<p>Si la vérification d’intégrité dans Nextcloud échoue, essayez de modifier le fichier config.php.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -u www-data sed -i "s/.*integrity.check.disabled.*/'integrity.check.disabled' => true,/g" /var/www/nextcloud/config/config.php
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Relancez le contrôle d’intégrité et redéfinissez la valeur sur ‘false’:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -u www-data sed -i "s/.*integrity.check.disabled.*/'integrity.check.disabled' => false,/g" /var/www/nextcloud/config/config.php
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Actualisez le adminpanel (F5) et le message devrait disparaître!</p>
|
|||
|
|
|||
|
<h2 id="6-durcissez-votre-système-avec-fail2ban-et-ufw">6. Durcissez votre système avec fail2ban et ufw</h2>
|
|||
|
|
|||
|
<p>Commencez par installer et configurer fail2ban, puis configurez le pare-feu ufw pour sécuriser Nextcloud.</p>
|
|||
|
|
|||
|
<h3 id="installer-et-configurer-fail2ban">Installer et configurer fail2ban</h3>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt update && apt install fail2ban -y
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Collez les lignes suivantes dans le filtre fail2ban pour Nextcloud (ou <a href="https://privat.c-rieger.de/s/88dQxRYYsoR3K2Y/download?path=%2F&files=nextcloud.txt">téléchargez-les en tant que fichier txt</a> pour éviter les problèmes de code WordPress!):</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/fail2ban/filter.d/nextcloud.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[Definition]
|
|||
|
failregex=^{"reqId":".*","remoteAddr":".*","app":"core","message":"Login failed: '.*' \(Remote IP: '<HOST>'\)","level":2,"time":".*"}$
|
|||
|
^{"reqId":".*","level":2,"time":".*","remoteAddr":".*","app":"core".*","message":"Login failed: '.*' \(Remote IP: '<HOST>'\)".*}$
|
|||
|
^.*\"remoteAddr\":\"<HOST>\".*Trusted domain error.*$
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Collez les lignes suivantes dans la prison fail2ban pour Nextcloud:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/fail2ban/jail.d/nextcloud.local
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[nextcloud]
|
|||
|
backend = auto
|
|||
|
enabled = true
|
|||
|
port = 80,443
|
|||
|
protocol = tcp
|
|||
|
filter = nextcloud
|
|||
|
maxretry = 3
|
|||
|
bantime = 36000
|
|||
|
findtime = 36000
|
|||
|
logpath = /var/nc_data/nextcloud.log
|
|||
|
|
|||
|
[nginx-http-auth]
|
|||
|
enabled = true
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="redémarrez-le-service-fail2ban">Redémarrez le service fail2ban</h3>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>service fail2ban restart && fail2ban-client status nextcloud
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="configurez-votre-ufw-pare-feu-simple">Configurez votre ufw (pare-feu simple)</h3>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt install ufw -y
|
|||
|
ufw allow 80/tcp && ufw allow 443/tcp && ufw allow 22/tcp && ufw logging medium
|
|||
|
ufw default deny incoming && ufw enable && service ufw restart
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="61-renforcez-votre-nextcloud-avec-spamhaus-project-et-ufw">6.1 Renforcez votre Nextcloud avec Spamhaus Project et UFW</h2>
|
|||
|
|
|||
|
<p>Si vous souhaitez éviter les «visiteurs non privilégiés», créez simplement le script /root/ufw-spamhaus.sh et bloquez-les directement par ufw.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /root/ufw-spamhaus.sh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Collez les lignes suivantes:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#!/bin/bash
|
|||
|
# Thanks to @ank0m
|
|||
|
EXEC_DATE=`date +%Y-%m-%d`
|
|||
|
SPAMHAUS_DROP="/usr/local/src/drop.txt"
|
|||
|
SPAMHAUS_eDROP="/usr/local/src/edrop.txt"
|
|||
|
URL="https://www.spamhaus.org/drop/drop.txt"
|
|||
|
eURL="https://www.spamhaus.org/drop/edrop.txt"
|
|||
|
DROP_ADD_TO_UFW="/usr/local/src/DROP2.txt"
|
|||
|
eDROP_ADD_TO_UFW="/usr/local/src/eDROP2.txt"
|
|||
|
DROP_ARCHIVE_FILE="/usr/local/src/DROP_$EXEC_DATE"
|
|||
|
eDROP_ARCHIVE_FILE="/usr/local/src/eDROP_$EXEC_DATE"
|
|||
|
# All credits for the following BLACKLISTS goes to "The Spamhaus Project" - https://www.spamhaus.org
|
|||
|
echo "Start time: $(date)"
|
|||
|
echo " "
|
|||
|
echo "Download daily DROP file:"
|
|||
|
wget -q -O - "$URL" > $SPAMHAUS_DROP
|
|||
|
grep -v '^;' $SPAMHAUS_DROP | cut -d ' ' -f 1 > $DROP_ADD_TO_UFW
|
|||
|
echo " "
|
|||
|
echo "Extract DROP IP addresses and add to UFW:"
|
|||
|
cat $DROP_ADD_TO_UFW | while read line
|
|||
|
do
|
|||
|
/usr/sbin/ufw insert 1 deny from "$line" comment 'DROP_Blacklisted_IPs'
|
|||
|
done
|
|||
|
echo " "
|
|||
|
echo "Downloading eDROP list and import to UFW"
|
|||
|
echo " "
|
|||
|
echo "Download daily eDROP file:"
|
|||
|
wget -q -O - "$eURL" > $SPAMHAUS_eDROP
|
|||
|
grep -v '^;' $SPAMHAUS_eDROP | cut -d ' ' -f 1 > $eDROP_ADD_TO_UFW
|
|||
|
echo " "
|
|||
|
echo "Extract eDROP IP addresses and add to UFW:"
|
|||
|
cat $eDROP_ADD_TO_UFW | while read line
|
|||
|
do
|
|||
|
/usr/sbin/ufw insert 1 deny from "$line" comment 'eDROP_Blacklisted_IPs'
|
|||
|
done
|
|||
|
echo " "
|
|||
|
#####
|
|||
|
## To remove or revert these rules, keep the list of IPs!
|
|||
|
## Run a command like so to remove the rules:
|
|||
|
# while read line; do ufw delete deny from $line; done < $ARCHIVE_FILE
|
|||
|
#####
|
|||
|
echo "Backup DROP IP address list:"
|
|||
|
mv $DROP_ADD_TO_UFW $DROP_ARCHIVE_FILE
|
|||
|
echo " "
|
|||
|
echo "Backup eDROP IP address list:"
|
|||
|
mv $eDROP_ADD_TO_UFW $eDROP_ARCHIVE_FILE
|
|||
|
echo " "
|
|||
|
echo End time: $(date)
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Rendre le script exuable en émettant</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chmod +x /root/ufw-spamhaus.sh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>et configurez-le dans votre crontab pour qu’il soit émis automatiquement.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(crontab -l ; echo "10 2 * * * /root/ufw-spamhaus.sh 2>&1") | crontab -u root -
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Enfin effectuer une première exécution</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/root/ufw-spamhaus.sh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>et de nombreuses règles UFW seront appliquées immédiatement. Soyez patient, cela peut prendre un certain temps.</p>
|
|||
|
|
|||
|
<h2 id="7-surveillez-lensemble-de-votre-système-à-laide-de-netdata">7. Surveillez l’ensemble de votre système à l’aide de netdata</h2>
|
|||
|
|
|||
|
<p>Démarrer le téléchargement netdata - le répertoire ‘netdata’ sera créé</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt install apache2-utils git gcc make autoconf automake pkg-config uuid-dev zlib1g-dev
|
|||
|
cd /usr/local/src
|
|||
|
git clone https://github.com/firehol/netdata.git --depth=1
|
|||
|
cd netdata
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Créez un fichier de mot de passe pour protéger netdata:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>htpasswd -c /etc/nginx/netdata-access YourName
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ensuite, exécutez le script netdata-installer.sh avec les privilèges root pour créer, installer et démarrer netdata.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./netdata-installer.sh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Netdata est déjà installé. Nous ferons de petits ajustements à la configuration de netdata:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/netdata/netdata.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Dans un premier temps, nous modifions la valeur pour «historique», par exemple, 14400 (4 heures de conservation des données de graphique, utilise environ 60 Mo de RAM) dans la section [global]:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>history = 14400
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ensuite, nous modifions la liaison dans la section [web] en localhost (127.0.0.1) uniquement:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bind to = 127.0.0.1
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Enfin, nous améliorons les fichiers nextcloud.conf et nginx.conf pour inclure la configuration du serveur Web Netdata:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/nginx/conf.d/nextcloud.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Collez les lignes comme indiqué ci-dessous dans le fichier nextcloud.conf:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...
|
|||
|
location / {
|
|||
|
rewrite ^ /index.php$request_uri;
|
|||
|
}
|
|||
|
location /netdata {
|
|||
|
return 301 /netdata/;
|
|||
|
}
|
|||
|
### début insertion
|
|||
|
location ~ /netdata/(?<ndpath>.*) {
|
|||
|
auth_basic "Restricted Area";
|
|||
|
auth_basic_user_file /etc/nginx/netdata-access;
|
|||
|
proxy_http_version 1.1;
|
|||
|
proxy_pass_request_headers on;
|
|||
|
proxy_set_header Connection "keep-alive";
|
|||
|
proxy_store off;
|
|||
|
proxy_pass http://netdata/$ndpath$is_args$args;
|
|||
|
gzip on;
|
|||
|
gzip_proxied any;
|
|||
|
gzip_types *;
|
|||
|
}
|
|||
|
### fin insertion
|
|||
|
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
|
|||
|
deny all;
|
|||
|
...
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Créez le nouveau fichier /etc/nginx/conf.d/stub_status.conf:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/nginx/conf.d/stub_status.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Collez toutes les lignes suivantes:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
|
|||
|
listen 127.0.0.1:80 default_server;
|
|||
|
server_name 127.0.0.1;
|
|||
|
location /stub_status {
|
|||
|
stub_status on;
|
|||
|
allow 127.0.0.1;
|
|||
|
deny all;
|
|||
|
}
|
|||
|
}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Enregistrez et quittez le fichier (: wq!) Et modifiez le fichier /etc/nginx/nginx.conf:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...
|
|||
|
http {
|
|||
|
server_names_hash_bucket_size 64;
|
|||
|
upstream php-handler {
|
|||
|
server unix:/run/php/php7.3-fpm.sock;
|
|||
|
}
|
|||
|
## début modif
|
|||
|
upstream netdata {
|
|||
|
server 127.0.0.1:19999;
|
|||
|
keepalive 64;
|
|||
|
}
|
|||
|
## fin modif
|
|||
|
...
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Enregistrez et quittez le fichier (: wq!) Et vérifiez NGINX</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nginx -t
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Si aucune erreur n’apparaît, redémarrez netdata et nginx</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>service netdata restart && service nginx restart
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>et appelez netdata dans votre navigateur</p>
|
|||
|
|
|||
|
<p>https: // votre.dedyn.io / netdata</p>
|
|||
|
|
|||
|
<p>ou en tant que site externe dans votre Nextcloud.</p>
|
|||
|
|
|||
|
<h2 id="8-montez-un-espace-de-stockage-supplémentaire-sur-votre-nextcloud">8. Montez un espace de stockage supplémentaire sur votre Nextcloud</h2>
|
|||
|
|
|||
|
<p>(a) …<a href="https://www.c-rieger.de/nextcloud-installation-guide-debian/#storage01">using a NAS</a></p>
|
|||
|
|
|||
|
<p>(b) …<a href="https://www.c-rieger.de/nextcloud-installation-guide-debian/#storage02">using an external/additional HDD</a></p>
|
|||
|
|
|||
|
<p>(c) … <a href="https://www.c-rieger.de/nextcloud-installation-guide-debian/#storage03">using Nextclouds external storage app</a></p>
|
|||
|
|
|||
|
<p>Vous pouvez améliorer votre Nextcloud avec des données de votre partage NAS ou d’un disque dur externe.</p>
|
|||
|
|
|||
|
<h3 id="a-montez-vos-données-nas-sur-un-utilisateur-nextcloud-spécifique">(a) montez vos données NAS sur un utilisateur Nextcloud spécifique</h3>
|
|||
|
|
|||
|
<p>Il est très simple de monter un partage NAS sur votre Nextcloud à l’aide de cifs. Commencez par installer cifs-utils:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt install cifs-utils -y
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Puis stockez vos informations d’identification dans un fichier spécial (par exemple, /root/.smbcredentials )</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /root/.smbcredentials
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ecrivez votre nom d’utilisateur et mot de passe:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>username=NASuser
|
|||
|
password=NASPassword
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Enregistrez et quittez le fichier (: wq!) Et modifiez les autorisations en 0600:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chmod 400 /root/.smbcredentials
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Détectez l’ID de l’utilisateur Web (www-data) à l’aide de la commande id:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>id www-data
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>et gardez l’identifiant à l’esprit pour le réutiliser dans / etc / fstab :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cp /etc/fstab /etc/fstab.bak
|
|||
|
vi /etc/fstab
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Coller ce qui suit jusqu’à la fin du fstab</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//<NAS>/<share> /var/nc_data/next/files cifs user,uid=33,rw,iocharset=utf8,suid,credentials=/root/.smbcredentials,file_mode=0770,dir_mode=0770 0 0
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Veuillez remplacer **“//<NAS>/<share>“** par le suivant et, si nécessaire, l'uid = « 33 », puis essayez de monter votre NAS manuellement:</share></NAS></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mount //<NAS>/<share>/
|
|||
|
ou
|
|||
|
mount -a
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Pour démonter votre NAS, lancez manuellement</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>umount //<NAS>/<share>/
|
|||
|
ou
|
|||
|
umount -a
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Il sera nécessaire de numériser à nouveau vos données pour la première utilisation. Allez donc dans votre répertoire Nextcloud et exécutez les fichiers Nextclouds : recherchez l’utilisateur Nextcloud approprié (par exemple, next ) ou all ( –all ):</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>service nginx stop
|
|||
|
cd /var/www/nextcloud
|
|||
|
redis-cli -s /var/run/redis/redis.sock
|
|||
|
FLUSHALL
|
|||
|
quit
|
|||
|
sudo -u www-data php occ files:scan --all -v
|
|||
|
sudo -u www-data php occ files:scan-app-data -v
|
|||
|
service nginx start
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Après les fichiers Nextclouds: analyser toutes vos données NAS apparaîtra dans l’application de fichier Nextcloud.<br />
|
|||
|
Le script de permissions <permission.sh> devrait être amélioré pour démonter et monter le nouveau partage NAS monté:</permission.sh></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /root/permissions.sh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ajoutez les lignes rouges au script existant:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#!/bin/bash
|
|||
|
find /var/www/ -type f -print0 | xargs -0 chmod 0640
|
|||
|
find /var/www/ -type d -print0 | xargs -0 chmod 0750
|
|||
|
chown -R www-data:www-data /var/www/
|
|||
|
umount //<NAS>/<share>
|
|||
|
chown -R www-data:www-data /var/nc_data/
|
|||
|
mount //<NAS>/<share>
|
|||
|
chmod 0644 /var/www/nextcloud/.htaccess
|
|||
|
chmod 0644 /var/www/nextcloud/.user.ini
|
|||
|
chmod 600 /etc/letsencrypt/rsa-certs/fullchain.pem
|
|||
|
chmod 600 /etc/letsencrypt/rsa-certs/privkey.pem
|
|||
|
chmod 600 /etc/letsencrypt/rsa-certs/chain.pem
|
|||
|
chmod 600 /etc/letsencrypt/rsa-certs/cert.pem
|
|||
|
chmod 600 /etc/letsencrypt/ecc-certs/fullchain.pem
|
|||
|
chmod 600 /etc/letsencrypt/ecc-certs/privkey.pem
|
|||
|
chmod 600 /etc/letsencrypt/ecc-certs/chain.pem
|
|||
|
chmod 600 /etc/letsencrypt/ecc-certs/cert.pem
|
|||
|
chmod 600 /etc/ssl/certs/dhparam.pem
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Veuillez substituer les <code class="language-plaintext highlighter-rouge">mount umount //<NAS>/<share></code> en fonction de votre environnement, puis enregistrez et quittez (: wq!) Le fichier. A partir de maintenant, votre NAS sera toujours disponible dans Nextcloud pour l’utilisateur spécifique.</p>
|
|||
|
|
|||
|
<h3 id="b-monter-un-disque-dur-externe-sur-votre-nextcloud">(b) monter un disque dur externe sur votre Nextcloud</h3>
|
|||
|
|
|||
|
<p>Nous préparons le nouveau lecteur ‘/dev/sda ‘ pour utilisation dans Nextcloud. Formatez-le avec un système de fichiers ‘ext4’ et montez-le de manière permanente avec une entrée dans / etc / fstab.</p>
|
|||
|
|
|||
|
<p>Arrêtez vos services de serveur (NGINX, PHP, MariaDB, Redis) et vérifiez la disponibilité du nouveau lecteur:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
|
|||
|
service nginx stop && service php7.3-fpm stop && service redis-server stop && service mysql stop
|
|||
|
fdisk -l /dev/sda
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Si disponible, créez une nouvelle partition avec la commande fdisk.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>fdisk /dev/sda
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<ol>
|
|||
|
<li>Tapez ‘o’ pour créer une nouvelle table de partition.</li>
|
|||
|
<li>Tapez ‘n’ pour créer une nouvelle partition.</li>
|
|||
|
<li>Choisissez le type de partition principale, entrez ‘p’.</li>
|
|||
|
<li>Numéro de partition - nous avons juste besoin de 1.</li>
|
|||
|
<li>Laissez toutes les valeurs par défaut sur le premier secteur et le dernier secteur - Appuyez sur Entrée.</li>
|
|||
|
<li>Tapez ‘w’ et appuyez sur Entrée pour écrire la partition.</li>
|
|||
|
</ol>
|
|||
|
|
|||
|
<p>La partition ‘/dev/sda1’ a été créée, nous devons maintenant la formater en ‘ext4’ avec l’outil mkfs. Ensuite, vérifiez la taille du volume.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkfs.ext4 /dev/sda1
|
|||
|
fdisk -s /dev/sda1
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ensuite, créez un nouveau répertoire local “nc_data” et montez “/ dev / sda1” sur ce répertoire.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir -p /nc_data
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Pour monter définitivement un nouveau disque, nous ajoutons la nouvelle configuration de montage au fichier fstab. Fstab ouvert avec vom:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/fstab
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Collez la configuration ci-dessous à la fin du fichier.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/dev/sda1 /nc_data ext4 defaults 0 1
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Enregistrer fstab et quitter:</p>
|
|||
|
|
|||
|
<p>Maintenant, montez le disque et assurez-vous qu’il n’y a pas d’erreur.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mount -a
|
|||
|
df -h
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Au moins, vous devez déplacer votre répertoire de données Nextcloud actuel vers le nouveau répertoire monté.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chown -R www-data:www-data /nc_data
|
|||
|
rsync -av /var/nc_data/ /nc_data
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>et pointez-le dans le fichier config.php de Nextcloud.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -u www-data vi /var/www/nextcloud/config/config.php
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Changer le répertoire de données</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...
|
|||
|
'datadirectory' => '/nc_data',
|
|||
|
...
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Enfin, redémarrez les services de votre serveur et effectuez une nouvelle analyse de fichiers:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>service nginx stop && service php7.3-fpm restart && service redis-server restart && service mysql restart
|
|||
|
cd /var/www/nextcloud
|
|||
|
redis-cli -s /var/run/redis/redis.sock
|
|||
|
FLUSHALL
|
|||
|
quit
|
|||
|
sudo -u www-data php occ files:scan --all -v
|
|||
|
sudo -u www-data php occ files:scan-app-data -v
|
|||
|
service nginx restart
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>A partir de maintenant, vos données Nextcloud seront stockées sur votre disque dur externe.</p>
|
|||
|
|
|||
|
<h3 id="c-application-de-stockage-externe-nextclouds">(c) Application de stockage externe Nextclouds</h3>
|
|||
|
|
|||
|
<p>En tant qu’extension pour ( a ) et ( b ), vous pouvez activer l’ <a href="https://docs.nextcloud.com/server/15/admin_manual/configuration_files/external_storage_configuration_gui.html#configuring-external-storage-gui">application de stockage externe</a> et bénéficier de nombreux avantages:</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>les fichiers peuvent être créés, édités et supprimés des deux côtés: à l’intérieur et à l’extérieur de Nextcloud</li>
|
|||
|
<li>vous êtes autorisé à monter des services et des périphériques de stockage externes en tant que périphériques de stockage Nextcloud secondaires</li>
|
|||
|
<li>les utilisateurs sont autorisés à monter leurs propres services de stockage externe</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Si vous souhaitez utiliser Samba, émettez la déclaration suivante</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt install php-smbclient smbclient -y
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>et redémarrez PHP</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>service php7.3-fpm restart
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="9-installez-msmtp-pour-envoyer-des-mails-au-serveur">9. Installez msmtp pour envoyer des mails au serveur</h2>
|
|||
|
|
|||
|
<p>(a) <a href="https://www.c-rieger.de/nextcloud-installation-guide-debian/#fail2banmails">configure fail2ban system-notification mails</a></p>
|
|||
|
|
|||
|
<p>(b) <a href="https://www.c-rieger.de/nextcloud-installation-guide-debian/#apticronmails">install apticron and configure system update-notification mails</a></p>
|
|||
|
|
|||
|
<p>Première installation msmtp</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
|
|||
|
apt update && apt upgrade -y && apt install msmtp msmtp-mta mailutils -y
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Créez votre configuration: créez le fichier, puis collez et modifiez les lignes suivantes:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/msmtprc
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>defaults
|
|||
|
port 587
|
|||
|
tls on
|
|||
|
tls_starttls on
|
|||
|
tls_trust_file /etc/ssl/certs/ca-certificates.crt
|
|||
|
#Your Mail:
|
|||
|
account yourmail@domain.com
|
|||
|
#Your SMTP-Server:
|
|||
|
host smtp.domain.com
|
|||
|
#Mails will be sent from:
|
|||
|
from yourmail@domain.com
|
|||
|
auth on
|
|||
|
#Your Mailaccount:
|
|||
|
user yourmail@domain.com
|
|||
|
#Your Password:
|
|||
|
password yOUr-S3CrET
|
|||
|
#Default Mailaccount:
|
|||
|
account default: yourmail@domain.com
|
|||
|
aliases /etc/aliases
|
|||
|
# find out more about the configuration here: https://marlam.de/msmtp/msmtprc.txt
|
|||
|
logfile /var/log/msmtp/msmtp.log
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Définir la permission appropriée</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chmod 600 /etc/msmtprc
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>et testez votre configuration de serveur de courrier en émettant</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo "Sending test mail..." | mail -s "Subject" yourmail@domain.com
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Modifiez logrotate pour gérer correctement msmtp. Créer et éditer le fichier</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/logrotate.d/msmtp
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>et collez toutes les lignes suivantes:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/var/log/msmtp/*.log {
|
|||
|
rotate 12
|
|||
|
monthly
|
|||
|
compress
|
|||
|
missingok
|
|||
|
notifempty
|
|||
|
}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Modifier PHP pour utiliser msmtp dans PHP</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/php/7.3/fpm/php.ini
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Définissez le sendmail_path comme suit</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sendmail_path = "/usr/bin/msmtp -t"
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>et redémarrez php</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>service php7.3-fpm restart
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Définissez enfin vos alias de messagerie: ouvrez le fichier</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/aliases
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>coller et modifier les lignes suivantes:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>root: yourmail@domain.com
|
|||
|
default: yourmail@domain.com
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>A partir de maintenant votre système est préparé pour envoyer des mails. Si vous voulez que fail2ban vous tienne au courant, suivez le chapitre suivant:</p>
|
|||
|
|
|||
|
<h3 id="a-configurer-les-mails-de-notification-du-système-fail2ban">(a) configurer les mails de notification du système fail2ban</h3>
|
|||
|
|
|||
|
<p>Nous substituons l’utilisateur root dans fail2ban-config pour recevoir les mails d’état de fail2ban à l’avenir. Ces e-mails contiendront à la fois le statut fail2ban (arrêté / démarré) et, en cas d’échec de la connexion, l’adresse IP bannie. Editez le fichier de configuration fail2ban</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.conf.bak
|
|||
|
nano /etc/fail2ban/jail.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>et remplacez au moins les paramètres <strong>yourmail@domain.com, mail, action = %(action_mwl)s</strong> en fonction de votre système:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...
|
|||
|
destemail = yourmail@domain.com
|
|||
|
...
|
|||
|
sender = yourmail@domain.com
|
|||
|
...
|
|||
|
mta = mail
|
|||
|
...
|
|||
|
# action = %(action_)s
|
|||
|
action = %(action_mwl)s
|
|||
|
...
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Enregistrez et quittez (: wq!) La configuration fail2ban. Pour éviter (plusieurs) mails sur chaque redémarrage fail2ban, créez simplement un nouveau fichier et copiez-le comme indiqué ci-dessous:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/fail2ban/action.d/mail-buffered.local
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Coller les lignes suivantes</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[Definition]
|
|||
|
actionstart =
|
|||
|
actionstop =
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Copier le fichier</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cp /etc/fail2ban/action.d/mail-buffered.local /etc/fail2ban/action.d/mail.local
|
|||
|
cp /etc/fail2ban/action.d/mail-buffered.local /etc/fail2ban/action.d/mail-whois-lines.local
|
|||
|
cp /etc/fail2ban/action.d/mail-buffered.local /etc/fail2ban/action.d/mail-whois.local
|
|||
|
cp /etc/fail2ban/action.d/mail-buffered.local /etc/fail2ban/action.d/sendmail-buffered.local
|
|||
|
cp /etc/fail2ban/action.d/mail-buffered.local /etc/fail2ban/action.d/sendmail-common.local
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Redémarrez le service fail2ban et vous serez (seulement) informé si Fail2ban a bloqué de nouvelles adresses IP</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>service fail2ban restart
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>automatiquement</p>
|
|||
|
|
|||
|
<h3 id="b-installer-apticron-et-configurer-les-mails-de-notification-de-mise-à-jour-du-système">(b) installer apticron et configurer les mails de notification de mise à jour du système</h3>
|
|||
|
|
|||
|
<p>Si vous utilisez APTICRON, votre système peut également envoyer des courriels en cas de mises à jour système disponibles.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt install apticron -y
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Après avoir installé APTICRON, vous devez modifier la configuration et substituer au moins votre adresse EMAIL, SYSTEM, NOTIFY_NO_UPDATES et CUSTOM_FROM.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cp /etc/apticron/apticron.conf /etc/apticron/apticron.conf.bak
|
|||
|
nano /etc/apticron/apticron.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...
|
|||
|
EMAIL="yourmail@domain.com"
|
|||
|
...
|
|||
|
SYSTEM="your.dedyn.io"
|
|||
|
...
|
|||
|
NOTIFY_HOLDS="1"
|
|||
|
...
|
|||
|
NOTIFY_NO_UPDATES="1"
|
|||
|
...
|
|||
|
CUSTOM_SUBJECT='$SYSTEM: $NUM_PACKAGES package update(s)'
|
|||
|
...
|
|||
|
CUSTOM_NO_UPDATES_SUBJECT='$SYSTEM: no updates available'
|
|||
|
...
|
|||
|
CUSTOM_FROM="yourmail@domain.com"
|
|||
|
...
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Pour lancer et vérifier APTICRON, appelez simplement</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apticron
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>et vous recevrez un email envoyé par APTICRON. Maintenant, vous êtes un peu plus en sécurité.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cp /etc/cron.d/apticron /etc/cron.d/apticron.bak
|
|||
|
nano /etc/cron.d/apticron
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><code class="language-plaintext highlighter-rouge">30 7 * * * root if test -x /usr/sbin/apticron; then /usr/sbin/apticron --cron; else true; fi</code></p>
|
|||
|
|
|||
|
<p>Apticron va maintenant être exécuté par cron.d. Vous pouvez modifier l’heure de début, par exemple, tous les jours à 7 h 30.</p>
|
|||
|
|
|||
|
<h2 id="10-un-deuxième-facteur-pour-ssh-2fa---authentification-à-deux-facteurs">10. Un deuxième facteur pour ssh (2FA - authentification à deux facteurs)</h2>
|
|||
|
|
|||
|
<p>Les étapes suivantes concernent le système (critique) et ne sont recommandées que pour les utilisateurs avancés de Linux. Si la configuration de ssh échoue, vous ne pourrez plus vous connecter à votre système via ssh. La condition préalable requise est un serveur ssh sur lequel vous pouvez vous connecter à l’aide d’une clé privée / publique uniquement!</p>
|
|||
|
|
|||
|
<p>Installez le logiciel pour 2FA (authentification à deux facteurs) avec votre application OTP AUTH préférée.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt install libpam-google-authenticator -y
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Quittez le shell racine et exécutez la commande suivante en tant que votre <nom de="" votre-utilisateur-ubuntu=""> et PAS en tant que root:</nom></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>exit
|
|||
|
google-authenticator
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>On vous demandera:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Do you want authentication tokens to be time-based (y/n) y
|
|||
|
|
|||
|
image
|
|||
|
|
|||
|
Do you want me to update your "~/.google_authenticator" file (y/n) y
|
|||
|
|
|||
|
Do you want to disallow multiple uses of the same authentication
|
|||
|
token? This restricts you to one login about every 30s, but it increases
|
|||
|
your chances to notice or even prevent man-in-the-middle attacks (y/n) y
|
|||
|
|
|||
|
By default, tokens are good for 30 seconds and in order to compensate for
|
|||
|
possible time-skew between the client and the server, we allow an extra
|
|||
|
token before and after the current time. If you experience problems with poor
|
|||
|
time synchronization, you can increase the window from its default
|
|||
|
size of 1:30min to about 4min. Do you want to do so (y/n) n
|
|||
|
|
|||
|
If the computer that you are logging into isn't hardened against brute-force
|
|||
|
login attempts, you can enable rate-limiting for the authentication module.
|
|||
|
By default, this limits attackers to no more than 3 login attempts every 30s.
|
|||
|
Do you want to enable rate-limiting (y/n) y
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Revenez à la racine-Shell</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Sauvegardez la configuration actuelle et configurez votre serveur ssh</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cp /etc/pam.d/sshd /etc/pam.d/sshd.bak
|
|||
|
nano /etc/pam.d/sshd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Changer le fichier à la mienne:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@include common-auth
|
|||
|
@include common-password
|
|||
|
auth required pam_google_authenticator.so
|
|||
|
account required pam_nologin.so
|
|||
|
@include common-account
|
|||
|
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close
|
|||
|
session required pam_loginuid.so
|
|||
|
session optional pam_keyinit.so force revoke
|
|||
|
@include common-session
|
|||
|
session optional pam_motd.so motd=/run/motd.dynamic
|
|||
|
session optional pam_motd.so noupdate
|
|||
|
session optional pam_mail.so standard noenv # [1]
|
|||
|
session required pam_limits.so
|
|||
|
session required pam_env.so # [1]
|
|||
|
session required pam_env.so user_readenv=1 envfile=/etc/default/locale
|
|||
|
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Sauvegarder et quitter (: wq!) Le fichier.</p>
|
|||
|
|
|||
|
<p>S’il n’est pas déjà créé, créez d’abord votre clé RSA 4096 bits (SSH):</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd ~
|
|||
|
ssh-keygen -q -f /etc/ssh/ssh_host_rsa_key -N '' -b 4096 -t rsa
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Si vous êtes invité à écraser la clé existante, confirmez avec “Y”. Ensuite, sauvegardez, éditez et changez votre configuration SSH en un exemple</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mv /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
|
|||
|
nano /etc/ssh/sshd_config
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Port 22
|
|||
|
Port 1234 #your decision, but keep UFW in mind!
|
|||
|
Protocol 2
|
|||
|
HostKey /etc/ssh/ssh_host_rsa_key
|
|||
|
HostKey /etc/ssh/ssh_host_ecdsa_key
|
|||
|
HostKey /etc/ssh/ssh_host_ed25519_key
|
|||
|
UsePrivilegeSeparation yes
|
|||
|
KeyRegenerationInterval 3600
|
|||
|
ServerKeyBits 4096
|
|||
|
SyslogFacility AUTH
|
|||
|
LogLevel INFO
|
|||
|
LoginGraceTime 30s
|
|||
|
PermitRootLogin no
|
|||
|
StrictModes yes
|
|||
|
RSAAuthentication yes
|
|||
|
PubkeyAuthentication yes
|
|||
|
IgnoreRhosts yes
|
|||
|
UseDNS yes
|
|||
|
RhostsRSAAuthentication no
|
|||
|
HostbasedAuthentication no
|
|||
|
IgnoreUserKnownHosts yes
|
|||
|
PermitEmptyPasswords no
|
|||
|
MaxAuthTries 3
|
|||
|
MaxSessions 3
|
|||
|
ChallengeResponseAuthentication yes
|
|||
|
X11Forwarding yes
|
|||
|
X11DisplayOffset 10
|
|||
|
X11UseLocalhost no
|
|||
|
PrintMotd no
|
|||
|
PrintLastLog yes
|
|||
|
TCPKeepAlive yes
|
|||
|
Banner /etc/issue
|
|||
|
AcceptEnv LANG LC_*
|
|||
|
Subsystem sftp /usr/lib/openssh/sftp-server
|
|||
|
UsePAM yes
|
|||
|
AllowTcpForwarding no
|
|||
|
AllowUsers ubuntuuser #<your-ubuntu-user-name> for e.g. putty or ssh native
|
|||
|
AuthenticationMethods publickey,password publickey,keyboard-interactive
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Si vous avez changé le port ssh en 1234 , assurez-vous d’avoir modifié votre configuration ufw et ajustez le nom d’utilisateur dans ‘AllowUsers ubuntuuser ‘ .</p>
|
|||
|
|
|||
|
<p>Collez votre clé publique dans le magasin de clés de < ubuntuuser > (le guide d’utilisation d’ ubuntu):</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano ~/.ssh/authorized_keys
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>et définir les autorisations appropriées:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo chown -R ubuntuuser:ubuntuuser ~/.ssh
|
|||
|
sudo chmod 700 ~/.ssh
|
|||
|
sudo chmod 600 ~/.ssh/authorized_keys
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Puis redémarrez votre serveur ssh</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>service ssh restart
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>et reconnectez-vous à votre serveur en utilisant une nouvelle fenêtre de session . Ceci est votre dernier recours si vous avez mal configuré votre serveur ssh ;-). A partir de maintenant votre clé privée est nécessaire, vous serez invité à entrer votre mot de passe et enfin votre nouveau deuxième facteur.</p>
|
|||
|
|
|||
|
<p>image1<br />
|
|||
|
Authentification par clé publique et mot de passe ssh-user</p>
|
|||
|
|
|||
|
<p>image2<br />
|
|||
|
Code de vérification (OTP 2FA)</p>
|
|||
|
|
|||
|
<p>Démarrez votre application, par exemple OTP AUTH ou Google Authenticator, et lisez votre deuxième facteur pour accéder à votre serveur.</p>
|
|||
|
|
|||
|
<p>image3<br />
|
|||
|
Connecté</p>
|
|||
|
|
|||
|
<p>Vous serez connecté en utilisant votre deuxième facteur.</p>
|
|||
|
|
|||
|
<h2 id="11-analysez-votre-serveur-en-utilisant-logwatch">11. Analysez votre serveur en utilisant logwatch</h2>
|
|||
|
|
|||
|
<p>Première installation de logwatch</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt update && apt install logwatch -y
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>puis copiez les fichiers de configuration par défaut dans le dossier logwatch:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cp /usr/share/logwatch/default.conf/logfiles/http.conf /etc/logwatch/conf/logfiles/nginx.conf
|
|||
|
cp /usr/share/logwatch/default.conf/services/http.conf /etc/logwatch/conf/services/nginx.conf
|
|||
|
cp /usr/share/logwatch/scripts/services/http /usr/share/logwatch/scripts/services/nginx
|
|||
|
cp /usr/share/logwatch/default.conf/services/http-error.conf /etc/logwatch/conf/services/nginx-error.conf
|
|||
|
cp /usr/share/logwatch/scripts/services/http-error /etc/logwatch/scripts/services/nginx-error
|
|||
|
cp /etc/logwatch/conf/logfiles/nginx.conf /etc/logwatch/conf/logfiles/nginx.conf.org.bak
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Editez le fichier /etc/logwatch/conf/logfiles/nginx.conf pour le mien</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/logwatch/conf/logfiles/nginx.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Remplacez le fichier entier par:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>########################################################
|
|||
|
# Define log file group for NGINX
|
|||
|
########################################################
|
|||
|
|
|||
|
# What actual file? Defaults to LogPath if not absolute path....
|
|||
|
#LogFile = httpd/*access_log
|
|||
|
#LogFile = apache/*access.log.1
|
|||
|
#LogFile = apache/*access.log
|
|||
|
#LogFile = apache2/*access.log.1
|
|||
|
#LogFile = apache2/*access.log
|
|||
|
#LogFile = apache2/*access_log
|
|||
|
#LogFile = apache-ssl/*access.log.1
|
|||
|
#LogFile = apache-ssl/*access.log
|
|||
|
LogFile = nginx/*access.log
|
|||
|
LogFile = nginx/*error.log
|
|||
|
LogFile = nginx/*access.log.1
|
|||
|
LogFile = nginx/*error.log.1
|
|||
|
|
|||
|
# If the archives are searched, here is one or more line
|
|||
|
# (optionally containing wildcards) that tell where they are...
|
|||
|
#If you use a "-" in naming add that as well -mgt
|
|||
|
#Archive = archiv/httpd/*access_log.*
|
|||
|
#Archive = httpd/*access_log.*
|
|||
|
#Archive = apache/*access.log.*.gz
|
|||
|
#Archive = apache2/*access.log.*.gz
|
|||
|
#Archive = apache2/*access_log.*.gz
|
|||
|
#Archive = apache-ssl/*access.log.*.gz
|
|||
|
#Archive = archiv/httpd/*access_log-*
|
|||
|
#Archive = httpd/*access_log-*
|
|||
|
#Archive = apache/*access.log-*.gz
|
|||
|
#Archive = apache2/*access.log-*.gz
|
|||
|
#Archive = apache2/*access_log-*.gz
|
|||
|
#Archive = apache-ssl/*access.log-*.gz
|
|||
|
Archive = nginx/*access.log.*.gz
|
|||
|
Archive = nginx/*error.log.*.gz
|
|||
|
|
|||
|
# Expand the repeats (actually just removes them now)
|
|||
|
*ExpandRepeats
|
|||
|
|
|||
|
# Keep only the lines in the proper date range...
|
|||
|
*ApplyhttpDate
|
|||
|
|
|||
|
# vi: shiftwidth=3 tabstop=3 et
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Enregistrez et quittez (: wq!) Ce fichier et modifiez /etc/logwatch/conf/services/nginx.conf:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cp /etc/logwatch/conf/services/nginx.conf /etc/logwatch/conf/services/nginx.conf.org.bak
|
|||
|
vi /etc/logwatch/conf/services/nginx.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Changez le nom de http en NGINX ou remplacez le fichier entier par le mien:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>###########################################################################
|
|||
|
# Configuration file for NGINX filter
|
|||
|
###########################################################################
|
|||
|
|
|||
|
Title = "NGINX"
|
|||
|
|
|||
|
# Which logfile group...
|
|||
|
LogFile = NGINX
|
|||
|
|
|||
|
# Define the log file format
|
|||
|
#
|
|||
|
# This is now the same as the LogFormat parameter in the configuration file
|
|||
|
# for httpd. Multiple instances of declared LogFormats in the httpd
|
|||
|
# configuration file can be declared here by concatenating them with the
|
|||
|
# '|' character. The default, shown below, includes the Combined Log Format,
|
|||
|
# the Common Log Format, and the default SSL log format.
|
|||
|
#$LogFormat = "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"|%h %l %u %t \"%r\" %>s %b|%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
|
|||
|
|
|||
|
# The following is supported for backwards compatibility, but deprecated:
|
|||
|
# Define the log file format
|
|||
|
#
|
|||
|
# the only currently supported fields are:
|
|||
|
# client_ip
|
|||
|
# request
|
|||
|
# http_rc
|
|||
|
# bytes_transfered
|
|||
|
# agent
|
|||
|
#
|
|||
|
#$HTTP_FIELDS = "client_ip ident userid timestamp request http_rc bytes_transfered referrer agent"
|
|||
|
#$HTTP_FORMAT = "space space space brace quote space space quote quote"
|
|||
|
# Define the field formats
|
|||
|
#
|
|||
|
# the only currently supported formats are:
|
|||
|
# space = space delimited field
|
|||
|
# quote = quoted ("..") space delimited field
|
|||
|
# brace = braced ([..]) space delimited field
|
|||
|
|
|||
|
# Flag to ignore 4xx and 5xx error messages as possible hack attempts
|
|||
|
#
|
|||
|
# Set flag to 1 to enable ignore
|
|||
|
# or set to 0 to disable
|
|||
|
$HTTP_IGNORE_ERROR_HACKS = 0
|
|||
|
|
|||
|
# Ignore requests
|
|||
|
# Note - will not do ANY processing, counts, etc... just skip it and go to
|
|||
|
# the next entry in the log file.
|
|||
|
# Note - The match will be case insensitive; e.g. /model/ == /MoDel/
|
|||
|
# Examples:
|
|||
|
# 1. Ignore all URLs starting with /model/ and ending with 1 to 10 digits
|
|||
|
# $HTTP_IGNORE_URLS = ^/model/\d{1,10}$
|
|||
|
#
|
|||
|
# 2. Ignore all URLs starting with /model/ and ending with 1 to 10 digits and
|
|||
|
# all URLS starting with /photographer and ending with 1 to 10 digits
|
|||
|
# $HTTP_IGNORE_URLS = ^/model/\d{1,10}$|^/photographer/\d{1,10}$
|
|||
|
# or simply:
|
|||
|
# $HTTP_IGNORE_URLS = ^/(model|photographer)/\d{1,10}$
|
|||
|
|
|||
|
# To ignore a range of IP addresses completely from the log analysis,
|
|||
|
# set $HTTP_IGNORE_IPS. For example, to ignore all local IP addresses:
|
|||
|
#
|
|||
|
# $HTTP_IGNORE_IPS = ^10\.|^172\.(1[6-9]|2[0-9]|3[01])\.|^192\.168\.|^127\.
|
|||
|
#
|
|||
|
|
|||
|
# For more sophisticated ignore rules, you can define HTTP_IGNORE_EVAL
|
|||
|
# to an arbitrary chunk of code.
|
|||
|
# The default is not to filter anything:
|
|||
|
$HTTP_IGNORE_EVAL = 0
|
|||
|
# Example:
|
|||
|
# $HTTP_IGNORE_EVAL = "($field{http_rc} == 401) && ($field{client_ip}=~/^192\.168\./) && ($field{url}=~m%^/protected1/%)"
|
|||
|
# See the "scripts/services/http" script for other variables that can be tested.
|
|||
|
|
|||
|
# The variable $HTTP_USER_DISPLAY defines which user accesses are displayed.
|
|||
|
# The default is not to display user accesses:
|
|||
|
$HTTP_USER_DISPLAY = 0
|
|||
|
# To display access failures:
|
|||
|
# $HTTP_USER_DISPLAY = "$field{http_rc} >= 400"
|
|||
|
# To display all user accesses except "Unauthorized":
|
|||
|
# $HTTP_USER_DISPLAY = "$field{http_rc} != 401"
|
|||
|
|
|||
|
# To raise the needed level of detail for one or more specific
|
|||
|
# error codes to display a summary instead of listing each
|
|||
|
# occurrence, set a variable like the following ones:
|
|||
|
# Raise 403 codes to detail level High
|
|||
|
#$http_rc_detail_rep_403 = 10
|
|||
|
# Always show only summary for 404 codes
|
|||
|
#$http_rc_detail_rep_404 = 20
|
|||
|
|
|||
|
# vi: shiftwidth=3 tabstop=3 et
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Enregistrez et quittez le fichier (: wq!) Et désactivez les fichiers de configuration apache par défaut:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd /usr/share/logwatch/default.conf/services
|
|||
|
mv http-error.conf http-error.conf.bak && mv http.conf http.conf.bak
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Au moins, nous créons un cronjob pour envoyer le résultat de logwatch automatiquement:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>crontab -e
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Collez la ligne suivante:</p>
|
|||
|
|
|||
|
<p><code class="language-plaintext highlighter-rouge">@daily /usr/sbin/logwatch --output mail --mailto your@mail.com --format html --detail high --range yesterday > /dev/null 2>&1</code></p>
|
|||
|
|
|||
|
<p>Enregistrez et quittez crontab et vérifiez si logwatch est correctement configuré:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/usr/sbin/logwatch --output mail --mailto your@mail.com --format html --detail high --range yesterday
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vous devriez recevoir un email de logwatch qui ressemble à ceci:</p>
|
|||
|
|
|||
|
<p>image</p>
|
|||
|
|
|||
|
<p>A partir de maintenant, vous recevrez des mails quotidiens contenant votre résumé système.</p>
|
|||
|
|
|||
|
<p>Profitez de vos données personnelles sur votre Nextcloud-Server sécurisé et sécurisé!</p>
|
|||
|
|
|||
|
<h2 id="noubliez-pas-de-sauvegarder-votre-nextcloud">N’oubliez pas de sauvegarder votre Nextcloud</h2>
|
|||
|
|
|||
|
<p>Retrouvez plus d’instructions ici: <a href="https://www.c-rieger.de/nextcloud-backup-and-restore/">Sauvegarde et restauration Nextcloud (en)</a></p>
|
|||
|
|
|||
|
<h2 id="update-nextcloud-lien-hs"><a href="/files/html/Update Nextcloud.htm">Update Nextcloud-Lien HS</a></h2>
|
|||
|
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<div class="d-print-none"><footer class="article__footer"><meta itemprop="dateModified" content="2020-01-20T00:00:00+01:00"><!-- start custom article footer snippet -->
|
|||
|
|
|||
|
<!-- end custom article footer snippet -->
|
|||
|
<!--
|
|||
|
<div align="right"><a type="application/rss+xml" href="/feed.xml" title="S'abonner"><i class="fa fa-rss fa-2x"></i></a>
|
|||
|
|
|||
|
 </div>
|
|||
|
-->
|
|||
|
</footer>
|
|||
|
<div class="article__section-navigator clearfix"><div class="previous"><span>PRÉCÉDENT</span><a href="/2020/01/19/Portable-eeepc1001ha.html">Asus eeepc1001ha (noir) REV. 10/2020</a></div><div class="next"><span>SUIVANT</span><a href="/2020/02/08/grep-awk-sed.html">grep - awk - sed</a></div></div></div>
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
<script>(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
$(function() {
|
|||
|
var $this ,$scroll;
|
|||
|
var $articleContent = $('.js-article-content');
|
|||
|
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
|
|||
|
var scroll = hasSidebar ? '.js-page-main' : 'html, body';
|
|||
|
$scroll = $(scroll);
|
|||
|
|
|||
|
$articleContent.find('.highlight').each(function() {
|
|||
|
$this = $(this);
|
|||
|
$this.attr('data-lang', $this.find('code').attr('data-lang'));
|
|||
|
});
|
|||
|
$articleContent.find('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]').each(function() {
|
|||
|
$this = $(this);
|
|||
|
$this.append($('<a class="anchor d-print-none" aria-hidden="true"></a>').html('<i class="fas fa-anchor"></i>'));
|
|||
|
});
|
|||
|
$articleContent.on('click', '.anchor', function() {
|
|||
|
$scroll.scrollToAnchor('#' + $(this).parent().attr('id'), 400);
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
})();
|
|||
|
</script>
|
|||
|
|
|||
|
</div><section class="page__comments d-print-none"></section></article><!-- start custom main bottom snippet -->
|
|||
|
<!-- end custom main bottom snippet -->
|
|||
|
</div>
|
|||
|
</div></div></div></div>
|
|||
|
</div><script>(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
var $body = $('body'), $window = $(window);
|
|||
|
var $pageRoot = $('.js-page-root'), $pageMain = $('.js-page-main');
|
|||
|
var activeCount = 0;
|
|||
|
function modal(options) {
|
|||
|
var $root = this, visible, onChange, hideWhenWindowScroll = false;
|
|||
|
var scrollTop;
|
|||
|
function setOptions(options) {
|
|||
|
var _options = options || {};
|
|||
|
visible = _options.initialVisible === undefined ? false : show;
|
|||
|
onChange = _options.onChange;
|
|||
|
hideWhenWindowScroll = _options.hideWhenWindowScroll;
|
|||
|
}
|
|||
|
function init() {
|
|||
|
setState(visible);
|
|||
|
}
|
|||
|
function setState(isShow) {
|
|||
|
if (isShow === visible) {
|
|||
|
return;
|
|||
|
}
|
|||
|
visible = isShow;
|
|||
|
if (visible) {
|
|||
|
activeCount++;
|
|||
|
scrollTop = $(window).scrollTop() || $pageMain.scrollTop();
|
|||
|
$root.addClass('modal--show');
|
|||
|
$pageMain.scrollTop(scrollTop);
|
|||
|
activeCount === 1 && ($pageRoot.addClass('show-modal'), $body.addClass('of-hidden'));
|
|||
|
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.on('scroll', hide);
|
|||
|
$window.on('keyup', handleKeyup);
|
|||
|
} else {
|
|||
|
activeCount > 0 && activeCount--;
|
|||
|
$root.removeClass('modal--show');
|
|||
|
$window.scrollTop(scrollTop);
|
|||
|
activeCount === 0 && ($pageRoot.removeClass('show-modal'), $body.removeClass('of-hidden'));
|
|||
|
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.off('scroll', hide);
|
|||
|
$window.off('keyup', handleKeyup);
|
|||
|
}
|
|||
|
onChange && onChange(visible);
|
|||
|
}
|
|||
|
function show() {
|
|||
|
setState(true);
|
|||
|
}
|
|||
|
function hide() {
|
|||
|
setState(false);
|
|||
|
}
|
|||
|
function handleKeyup(e) {
|
|||
|
// Char Code: 27 ESC
|
|||
|
if (e.which === 27) {
|
|||
|
hide();
|
|||
|
}
|
|||
|
}
|
|||
|
setOptions(options);
|
|||
|
init();
|
|||
|
return {
|
|||
|
show: show,
|
|||
|
hide: hide,
|
|||
|
$el: $root
|
|||
|
};
|
|||
|
}
|
|||
|
$.fn.modal = modal;
|
|||
|
});
|
|||
|
})();
|
|||
|
</script><div class="modal modal--overflow page__search-modal d-print-none js-page-search-modal"><script>
|
|||
|
(function () {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
// search panel
|
|||
|
var search = (window.search || (window.search = {}));
|
|||
|
var useDefaultSearchBox = window.useDefaultSearchBox === undefined ?
|
|||
|
true : window.useDefaultSearchBox ;
|
|||
|
|
|||
|
var $searchModal = $('.js-page-search-modal');
|
|||
|
var $searchToggle = $('.js-search-toggle');
|
|||
|
var searchModal = $searchModal.modal({ onChange: handleModalChange, hideWhenWindowScroll: true });
|
|||
|
var modalVisible = false;
|
|||
|
search.searchModal = searchModal;
|
|||
|
|
|||
|
var $searchBox = null;
|
|||
|
var $searchInput = null;
|
|||
|
var $searchClear = null;
|
|||
|
|
|||
|
function getModalVisible() {
|
|||
|
return modalVisible;
|
|||
|
}
|
|||
|
search.getModalVisible = getModalVisible;
|
|||
|
|
|||
|
function handleModalChange(visible) {
|
|||
|
modalVisible = visible;
|
|||
|
if (visible) {
|
|||
|
search.onShow && search.onShow();
|
|||
|
useDefaultSearchBox && $searchInput[0] && $searchInput[0].focus();
|
|||
|
} else {
|
|||
|
search.onShow && search.onHide();
|
|||
|
useDefaultSearchBox && $searchInput[0] && $searchInput[0].blur();
|
|||
|
setTimeout(function() {
|
|||
|
useDefaultSearchBox && ($searchInput.val(''), $searchBox.removeClass('not-empty'));
|
|||
|
search.clear && search.clear();
|
|||
|
window.pageAsideAffix && window.pageAsideAffix.refresh();
|
|||
|
}, 400);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
$searchToggle.on('click', function() {
|
|||
|
modalVisible ? searchModal.hide() : searchModal.show();
|
|||
|
});
|
|||
|
// Char Code: 83 S, 191 /
|
|||
|
$(window).on('keyup', function(e) {
|
|||
|
if (!modalVisible && !window.isFormElement(e.target || e.srcElement) && (e.which === 83 || e.which === 191)) {
|
|||
|
modalVisible || searchModal.show();
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
if (useDefaultSearchBox) {
|
|||
|
$searchBox = $('.js-search-box');
|
|||
|
$searchInput = $searchBox.children('input');
|
|||
|
$searchClear = $searchBox.children('.js-icon-clear');
|
|||
|
search.getSearchInput = function() {
|
|||
|
return $searchInput.get(0);
|
|||
|
};
|
|||
|
search.getVal = function() {
|
|||
|
return $searchInput.val();
|
|||
|
};
|
|||
|
search.setVal = function(val) {
|
|||
|
$searchInput.val(val);
|
|||
|
};
|
|||
|
|
|||
|
$searchInput.on('focus', function() {
|
|||
|
$(this).addClass('focus');
|
|||
|
});
|
|||
|
$searchInput.on('blur', function() {
|
|||
|
$(this).removeClass('focus');
|
|||
|
});
|
|||
|
$searchInput.on('input', window.throttle(function() {
|
|||
|
var val = $(this).val();
|
|||
|
if (val === '' || typeof val !== 'string') {
|
|||
|
search.clear && search.clear();
|
|||
|
} else {
|
|||
|
$searchBox.addClass('not-empty');
|
|||
|
search.onInputNotEmpty && search.onInputNotEmpty(val);
|
|||
|
}
|
|||
|
}, 400));
|
|||
|
$searchClear.on('click', function() {
|
|||
|
$searchInput.val(''); $searchBox.removeClass('not-empty');
|
|||
|
search.clear && search.clear();
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
})();
|
|||
|
</script><div class="search search--dark">
|
|||
|
<div class="main">
|
|||
|
<div class="search__header">Recherche</div>
|
|||
|
<div class="search-bar">
|
|||
|
<div class="search-box js-search-box">
|
|||
|
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
|
|||
|
<input id="search-input" type="text" />
|
|||
|
<div class="search-box__icon-clear js-icon-clear">
|
|||
|
<a><i class="fas fa-times"></i></a>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<button class="button button--theme-dark button--pill search__cancel js-search-toggle">
|
|||
|
Annuler</button>
|
|||
|
</div>
|
|||
|
<div id="results-container" class="search-result js-search-result"></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<!-- Script pointing to search-script.js -->
|
|||
|
<script>/*!
|
|||
|
* Simple-Jekyll-Search
|
|||
|
* Copyright 2015-2020, Christian Fei
|
|||
|
* Licensed under the MIT License.
|
|||
|
*/
|
|||
|
|
|||
|
(function(){
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$Templater_7 = {
|
|||
|
compile: compile,
|
|||
|
setOptions: setOptions
|
|||
|
}
|
|||
|
|
|||
|
const options = {}
|
|||
|
options.pattern = /\{(.*?)\}/g
|
|||
|
options.template = ''
|
|||
|
options.middleware = function () {}
|
|||
|
|
|||
|
function setOptions (_options) {
|
|||
|
options.pattern = _options.pattern || options.pattern
|
|||
|
options.template = _options.template || options.template
|
|||
|
if (typeof _options.middleware === 'function') {
|
|||
|
options.middleware = _options.middleware
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function compile (data) {
|
|||
|
return options.template.replace(options.pattern, function (match, prop) {
|
|||
|
const value = options.middleware(prop, data[prop], options.template)
|
|||
|
if (typeof value !== 'undefined') {
|
|||
|
return value
|
|||
|
}
|
|||
|
return data[prop] || match
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
'use strict';
|
|||
|
|
|||
|
function fuzzysearch (needle, haystack) {
|
|||
|
var tlen = haystack.length;
|
|||
|
var qlen = needle.length;
|
|||
|
if (qlen > tlen) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
if (qlen === tlen) {
|
|||
|
return needle === haystack;
|
|||
|
}
|
|||
|
outer: for (var i = 0, j = 0; i < qlen; i++) {
|
|||
|
var nch = needle.charCodeAt(i);
|
|||
|
while (j < tlen) {
|
|||
|
if (haystack.charCodeAt(j++) === nch) {
|
|||
|
continue outer;
|
|||
|
}
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
var _$fuzzysearch_1 = fuzzysearch;
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
|
|||
|
|
|||
|
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
|
|||
|
|
|||
|
function FuzzySearchStrategy () {
|
|||
|
this.matches = function (string, crit) {
|
|||
|
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
|
|||
|
|
|||
|
function LiteralSearchStrategy () {
|
|||
|
this.matches = function (str, crit) {
|
|||
|
if (!str) return false
|
|||
|
|
|||
|
str = str.trim().toLowerCase()
|
|||
|
crit = crit.trim().toLowerCase()
|
|||
|
|
|||
|
return crit.split(' ').filter(function (word) {
|
|||
|
return str.indexOf(word) >= 0
|
|||
|
}).length === crit.split(' ').length
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$Repository_4 = {
|
|||
|
put: put,
|
|||
|
clear: clear,
|
|||
|
search: search,
|
|||
|
setOptions: __setOptions_4
|
|||
|
}
|
|||
|
|
|||
|
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
|
|||
|
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
|
|||
|
|
|||
|
function NoSort () {
|
|||
|
return 0
|
|||
|
}
|
|||
|
|
|||
|
const data = []
|
|||
|
let opt = {}
|
|||
|
|
|||
|
opt.fuzzy = false
|
|||
|
opt.limit = 10
|
|||
|
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
|
|||
|
opt.sort = NoSort
|
|||
|
opt.exclude = []
|
|||
|
|
|||
|
function put (data) {
|
|||
|
if (isObject(data)) {
|
|||
|
return addObject(data)
|
|||
|
}
|
|||
|
if (isArray(data)) {
|
|||
|
return addArray(data)
|
|||
|
}
|
|||
|
return undefined
|
|||
|
}
|
|||
|
function clear () {
|
|||
|
data.length = 0
|
|||
|
return data
|
|||
|
}
|
|||
|
|
|||
|
function isObject (obj) {
|
|||
|
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
|
|||
|
}
|
|||
|
|
|||
|
function isArray (obj) {
|
|||
|
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
|
|||
|
}
|
|||
|
|
|||
|
function addObject (_data) {
|
|||
|
data.push(_data)
|
|||
|
return data
|
|||
|
}
|
|||
|
|
|||
|
function addArray (_data) {
|
|||
|
const added = []
|
|||
|
clear()
|
|||
|
for (let i = 0, len = _data.length; i < len; i++) {
|
|||
|
if (isObject(_data[i])) {
|
|||
|
added.push(addObject(_data[i]))
|
|||
|
}
|
|||
|
}
|
|||
|
return added
|
|||
|
}
|
|||
|
|
|||
|
function search (crit) {
|
|||
|
if (!crit) {
|
|||
|
return []
|
|||
|
}
|
|||
|
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
|
|||
|
}
|
|||
|
|
|||
|
function __setOptions_4 (_opt) {
|
|||
|
opt = _opt || {}
|
|||
|
|
|||
|
opt.fuzzy = _opt.fuzzy || false
|
|||
|
opt.limit = _opt.limit || 10
|
|||
|
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
|
|||
|
opt.sort = _opt.sort || NoSort
|
|||
|
opt.exclude = _opt.exclude || []
|
|||
|
}
|
|||
|
|
|||
|
function findMatches (data, crit, strategy, opt) {
|
|||
|
const matches = []
|
|||
|
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
|
|||
|
const match = findMatchesInObject(data[i], crit, strategy, opt)
|
|||
|
if (match) {
|
|||
|
matches.push(match)
|
|||
|
}
|
|||
|
}
|
|||
|
return matches
|
|||
|
}
|
|||
|
|
|||
|
function findMatchesInObject (obj, crit, strategy, opt) {
|
|||
|
for (const key in obj) {
|
|||
|
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
|
|||
|
return obj
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function isExcluded (term, excludedTerms) {
|
|||
|
for (let i = 0, len = excludedTerms.length; i < len; i++) {
|
|||
|
const excludedTerm = excludedTerms[i]
|
|||
|
if (new RegExp(excludedTerm).test(term)) {
|
|||
|
return true
|
|||
|
}
|
|||
|
}
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
/* globals ActiveXObject:false */
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$JSONLoader_2 = {
|
|||
|
load: load
|
|||
|
}
|
|||
|
|
|||
|
function load (location, callback) {
|
|||
|
const xhr = getXHR()
|
|||
|
xhr.open('GET', location, true)
|
|||
|
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
|
|||
|
xhr.send()
|
|||
|
}
|
|||
|
|
|||
|
function createStateChangeListener (xhr, callback) {
|
|||
|
return function () {
|
|||
|
if (xhr.readyState === 4 && xhr.status === 200) {
|
|||
|
try {
|
|||
|
callback(null, JSON.parse(xhr.responseText))
|
|||
|
} catch (err) {
|
|||
|
callback(err, null)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function getXHR () {
|
|||
|
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$OptionsValidator_3 = function OptionsValidator (params) {
|
|||
|
if (!validateParams(params)) {
|
|||
|
throw new Error('-- OptionsValidator: required options missing')
|
|||
|
}
|
|||
|
|
|||
|
if (!(this instanceof OptionsValidator)) {
|
|||
|
return new OptionsValidator(params)
|
|||
|
}
|
|||
|
|
|||
|
const requiredOptions = params.required
|
|||
|
|
|||
|
this.getRequiredOptions = function () {
|
|||
|
return requiredOptions
|
|||
|
}
|
|||
|
|
|||
|
this.validate = function (parameters) {
|
|||
|
const errors = []
|
|||
|
requiredOptions.forEach(function (requiredOptionName) {
|
|||
|
if (typeof parameters[requiredOptionName] === 'undefined') {
|
|||
|
errors.push(requiredOptionName)
|
|||
|
}
|
|||
|
})
|
|||
|
return errors
|
|||
|
}
|
|||
|
|
|||
|
function validateParams (params) {
|
|||
|
if (!params) {
|
|||
|
return false
|
|||
|
}
|
|||
|
return typeof params.required !== 'undefined' && params.required instanceof Array
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$utils_9 = {
|
|||
|
merge: merge,
|
|||
|
isJSON: isJSON
|
|||
|
}
|
|||
|
|
|||
|
function merge (defaultParams, mergeParams) {
|
|||
|
const mergedOptions = {}
|
|||
|
for (const option in defaultParams) {
|
|||
|
mergedOptions[option] = defaultParams[option]
|
|||
|
if (typeof mergeParams[option] !== 'undefined') {
|
|||
|
mergedOptions[option] = mergeParams[option]
|
|||
|
}
|
|||
|
}
|
|||
|
return mergedOptions
|
|||
|
}
|
|||
|
|
|||
|
function isJSON (json) {
|
|||
|
try {
|
|||
|
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
|
|||
|
return true
|
|||
|
}
|
|||
|
return false
|
|||
|
} catch (err) {
|
|||
|
return false
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var _$src_8 = {};
|
|||
|
(function (window) {
|
|||
|
'use strict'
|
|||
|
|
|||
|
let options = {
|
|||
|
searchInput: null,
|
|||
|
resultsContainer: null,
|
|||
|
json: [],
|
|||
|
success: Function.prototype,
|
|||
|
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
|
|||
|
templateMiddleware: Function.prototype,
|
|||
|
sortMiddleware: function () {
|
|||
|
return 0
|
|||
|
},
|
|||
|
noResultsText: 'No results found',
|
|||
|
limit: 10,
|
|||
|
fuzzy: false,
|
|||
|
debounceTime: null,
|
|||
|
exclude: []
|
|||
|
}
|
|||
|
|
|||
|
let debounceTimerHandle
|
|||
|
const debounce = function (func, delayMillis) {
|
|||
|
if (delayMillis) {
|
|||
|
clearTimeout(debounceTimerHandle)
|
|||
|
debounceTimerHandle = setTimeout(func, delayMillis)
|
|||
|
} else {
|
|||
|
func.call()
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
|
|||
|
|
|||
|
/* removed: const _$Templater_7 = require('./Templater') */;
|
|||
|
/* removed: const _$Repository_4 = require('./Repository') */;
|
|||
|
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
|
|||
|
const optionsValidator = _$OptionsValidator_3({
|
|||
|
required: requiredOptions
|
|||
|
})
|
|||
|
/* removed: const _$utils_9 = require('./utils') */;
|
|||
|
|
|||
|
window.SimpleJekyllSearch = function (_options) {
|
|||
|
const errors = optionsValidator.validate(_options)
|
|||
|
if (errors.length > 0) {
|
|||
|
throwError('You must specify the following required options: ' + requiredOptions)
|
|||
|
}
|
|||
|
|
|||
|
options = _$utils_9.merge(options, _options)
|
|||
|
|
|||
|
_$Templater_7.setOptions({
|
|||
|
template: options.searchResultTemplate,
|
|||
|
middleware: options.templateMiddleware
|
|||
|
})
|
|||
|
|
|||
|
_$Repository_4.setOptions({
|
|||
|
fuzzy: options.fuzzy,
|
|||
|
limit: options.limit,
|
|||
|
sort: options.sortMiddleware,
|
|||
|
exclude: options.exclude
|
|||
|
})
|
|||
|
|
|||
|
if (_$utils_9.isJSON(options.json)) {
|
|||
|
initWithJSON(options.json)
|
|||
|
} else {
|
|||
|
initWithURL(options.json)
|
|||
|
}
|
|||
|
|
|||
|
const rv = {
|
|||
|
search: search
|
|||
|
}
|
|||
|
|
|||
|
typeof options.success === 'function' && options.success.call(rv)
|
|||
|
return rv
|
|||
|
}
|
|||
|
|
|||
|
function initWithJSON (json) {
|
|||
|
_$Repository_4.put(json)
|
|||
|
registerInput()
|
|||
|
}
|
|||
|
|
|||
|
function initWithURL (url) {
|
|||
|
_$JSONLoader_2.load(url, function (err, json) {
|
|||
|
if (err) {
|
|||
|
throwError('failed to get JSON (' + url + ')')
|
|||
|
}
|
|||
|
initWithJSON(json)
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function emptyResultsContainer () {
|
|||
|
options.resultsContainer.innerHTML = ''
|
|||
|
}
|
|||
|
|
|||
|
function appendToResultsContainer (text) {
|
|||
|
options.resultsContainer.innerHTML += text
|
|||
|
}
|
|||
|
|
|||
|
function registerInput () {
|
|||
|
options.searchInput.addEventListener('input', function (e) {
|
|||
|
if (isWhitelistedKey(e.which)) {
|
|||
|
emptyResultsContainer()
|
|||
|
debounce(function () { search(e.target.value) }, options.debounceTime)
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function search (query) {
|
|||
|
if (isValidQuery(query)) {
|
|||
|
emptyResultsContainer()
|
|||
|
render(_$Repository_4.search(query), query)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function render (results, query) {
|
|||
|
const len = results.length
|
|||
|
if (len === 0) {
|
|||
|
return appendToResultsContainer(options.noResultsText)
|
|||
|
}
|
|||
|
for (let i = 0; i < len; i++) {
|
|||
|
results[i].query = query
|
|||
|
appendToResultsContainer(_$Templater_7.compile(results[i]))
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function isValidQuery (query) {
|
|||
|
return query && query.length > 0
|
|||
|
}
|
|||
|
|
|||
|
function isWhitelistedKey (key) {
|
|||
|
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
|
|||
|
}
|
|||
|
|
|||
|
function throwError (message) {
|
|||
|
throw new Error('SimpleJekyllSearch --- ' + message)
|
|||
|
}
|
|||
|
})(window)
|
|||
|
|
|||
|
}());
|
|||
|
</script>
|
|||
|
|
|||
|
<!-- Configuration -->
|
|||
|
<script>
|
|||
|
SimpleJekyllSearch({
|
|||
|
searchInput: document.getElementById('search-input'),
|
|||
|
resultsContainer: document.getElementById('results-container'),
|
|||
|
noResultsText: '<p>Aucun résultat!</p>',
|
|||
|
json: '/search.json',
|
|||
|
searchResultTemplate: '<li><a href="{url}">{date} {title}</a> (Création {create})</li>'
|
|||
|
})
|
|||
|
</script>
|
|||
|
|
|||
|
</div></div>
|
|||
|
|
|||
|
|
|||
|
<script>(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
function scrollToAnchor(anchor, duration, callback) {
|
|||
|
var $root = this;
|
|||
|
$root.animate({ scrollTop: $(anchor).position().top }, duration, function() {
|
|||
|
window.history.replaceState(null, '', window.location.href.split('#')[0] + anchor);
|
|||
|
callback && callback();
|
|||
|
});
|
|||
|
}
|
|||
|
$.fn.scrollToAnchor = scrollToAnchor;
|
|||
|
});
|
|||
|
})();
|
|||
|
(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
function affix(options) {
|
|||
|
var $root = this, $window = $(window), $scrollTarget, $scroll,
|
|||
|
offsetBottom = 0, scrollTarget = window, scroll = window.document, disabled = false, isOverallScroller = true,
|
|||
|
rootTop, rootLeft, rootHeight, scrollBottom, rootBottomTop,
|
|||
|
hasInit = false, curState;
|
|||
|
|
|||
|
function setOptions(options) {
|
|||
|
var _options = options || {};
|
|||
|
_options.offsetBottom && (offsetBottom = _options.offsetBottom);
|
|||
|
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
|
|||
|
_options.scroll && (scroll = _options.scroll);
|
|||
|
_options.disabled !== undefined && (disabled = _options.disabled);
|
|||
|
$scrollTarget = $(scrollTarget);
|
|||
|
isOverallScroller = window.isOverallScroller($scrollTarget[0]);
|
|||
|
$scroll = $(scroll);
|
|||
|
}
|
|||
|
function preCalc() {
|
|||
|
top();
|
|||
|
rootHeight = $root.outerHeight();
|
|||
|
rootTop = $root.offset().top + (isOverallScroller ? 0 : $scrollTarget.scrollTop());
|
|||
|
rootLeft = $root.offset().left;
|
|||
|
}
|
|||
|
function calc(needPreCalc) {
|
|||
|
needPreCalc && preCalc();
|
|||
|
scrollBottom = $scroll.outerHeight() - offsetBottom - rootHeight;
|
|||
|
rootBottomTop = scrollBottom - rootTop;
|
|||
|
}
|
|||
|
function top() {
|
|||
|
if (curState !== 'top') {
|
|||
|
$root.removeClass('fixed').css({
|
|||
|
left: 0,
|
|||
|
top: 0
|
|||
|
});
|
|||
|
curState = 'top';
|
|||
|
}
|
|||
|
}
|
|||
|
function fixed() {
|
|||
|
if (curState !== 'fixed') {
|
|||
|
$root.addClass('fixed').css({
|
|||
|
left: rootLeft + 'px',
|
|||
|
top: 0
|
|||
|
});
|
|||
|
curState = 'fixed';
|
|||
|
}
|
|||
|
}
|
|||
|
function bottom() {
|
|||
|
if (curState !== 'bottom') {
|
|||
|
$root.removeClass('fixed').css({
|
|||
|
left: 0,
|
|||
|
top: rootBottomTop + 'px'
|
|||
|
});
|
|||
|
curState = 'bottom';
|
|||
|
}
|
|||
|
}
|
|||
|
function setState() {
|
|||
|
var scrollTop = $scrollTarget.scrollTop();
|
|||
|
if (scrollTop >= rootTop && scrollTop <= scrollBottom) {
|
|||
|
fixed();
|
|||
|
} else if (scrollTop < rootTop) {
|
|||
|
top();
|
|||
|
} else {
|
|||
|
bottom();
|
|||
|
}
|
|||
|
}
|
|||
|
function init() {
|
|||
|
if(!hasInit) {
|
|||
|
var interval, timeout;
|
|||
|
calc(true); setState();
|
|||
|
// run calc every 100 millisecond
|
|||
|
interval = setInterval(function() {
|
|||
|
calc();
|
|||
|
}, 100);
|
|||
|
timeout = setTimeout(function() {
|
|||
|
clearInterval(interval);
|
|||
|
}, 45000);
|
|||
|
window.pageLoad.then(function() {
|
|||
|
setTimeout(function() {
|
|||
|
clearInterval(interval);
|
|||
|
clearTimeout(timeout);
|
|||
|
}, 3000);
|
|||
|
});
|
|||
|
$scrollTarget.on('scroll', function() {
|
|||
|
disabled || setState();
|
|||
|
});
|
|||
|
$window.on('resize', function() {
|
|||
|
disabled || (calc(true), setState());
|
|||
|
});
|
|||
|
hasInit = true;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
setOptions(options);
|
|||
|
if (!disabled) {
|
|||
|
init();
|
|||
|
}
|
|||
|
$window.on('resize', window.throttle(function() {
|
|||
|
init();
|
|||
|
}, 200));
|
|||
|
return {
|
|||
|
setOptions: setOptions,
|
|||
|
refresh: function() {
|
|||
|
calc(true, { animation: false }); setState();
|
|||
|
}
|
|||
|
};
|
|||
|
}
|
|||
|
$.fn.affix = affix;
|
|||
|
});
|
|||
|
})();
|
|||
|
(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
function toc(options) {
|
|||
|
var $root = this, $window = $(window), $scrollTarget, $scroller, $tocUl = $('<ul class="toc toc--ellipsis"></ul>'), $tocLi, $headings, $activeLast, $activeCur,
|
|||
|
selectors = 'h1,h2,h3', container = 'body', scrollTarget = window, scroller = 'html, body', disabled = false,
|
|||
|
headingsPos, scrolling = false, hasRendered = false, hasInit = false;
|
|||
|
|
|||
|
function setOptions(options) {
|
|||
|
var _options = options || {};
|
|||
|
_options.selectors && (selectors = _options.selectors);
|
|||
|
_options.container && (container = _options.container);
|
|||
|
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
|
|||
|
_options.scroller && (scroller = _options.scroller);
|
|||
|
_options.disabled !== undefined && (disabled = _options.disabled);
|
|||
|
$headings = $(container).find(selectors).filter('[id]');
|
|||
|
$scrollTarget = $(scrollTarget);
|
|||
|
$scroller = $(scroller);
|
|||
|
}
|
|||
|
function calc() {
|
|||
|
headingsPos = [];
|
|||
|
$headings.each(function() {
|
|||
|
headingsPos.push(Math.floor($(this).position().top));
|
|||
|
});
|
|||
|
}
|
|||
|
function setState(element, disabled) {
|
|||
|
var scrollTop = $scrollTarget.scrollTop(), i;
|
|||
|
if (disabled || !headingsPos || headingsPos.length < 1) { return; }
|
|||
|
if (element) {
|
|||
|
$activeCur = element;
|
|||
|
} else {
|
|||
|
for (i = 0; i < headingsPos.length; i++) {
|
|||
|
if (scrollTop >= headingsPos[i]) {
|
|||
|
$activeCur = $tocLi.eq(i);
|
|||
|
} else {
|
|||
|
$activeCur || ($activeCur = $tocLi.eq(i));
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
$activeLast && $activeLast.removeClass('active');
|
|||
|
($activeLast = $activeCur).addClass('active');
|
|||
|
}
|
|||
|
function render() {
|
|||
|
if(!hasRendered) {
|
|||
|
$root.append($tocUl);
|
|||
|
$headings.each(function() {
|
|||
|
var $this = $(this);
|
|||
|
$tocUl.append($('<li></li>').addClass('toc-' + $this.prop('tagName').toLowerCase())
|
|||
|
.append($('<a></a>').text($this.text()).attr('href', '#' + $this.prop('id'))));
|
|||
|
});
|
|||
|
$tocLi = $tocUl.children('li');
|
|||
|
$tocUl.on('click', 'a', function(e) {
|
|||
|
e.preventDefault();
|
|||
|
var $this = $(this);
|
|||
|
scrolling = true;
|
|||
|
setState($this.parent());
|
|||
|
$scroller.scrollToAnchor($this.attr('href'), 400, function() {
|
|||
|
scrolling = false;
|
|||
|
});
|
|||
|
});
|
|||
|
}
|
|||
|
hasRendered = true;
|
|||
|
}
|
|||
|
function init() {
|
|||
|
var interval, timeout;
|
|||
|
if(!hasInit) {
|
|||
|
render(); calc(); setState(null, scrolling);
|
|||
|
// run calc every 100 millisecond
|
|||
|
interval = setInterval(function() {
|
|||
|
calc();
|
|||
|
}, 100);
|
|||
|
timeout = setTimeout(function() {
|
|||
|
clearInterval(interval);
|
|||
|
}, 45000);
|
|||
|
window.pageLoad.then(function() {
|
|||
|
setTimeout(function() {
|
|||
|
clearInterval(interval);
|
|||
|
clearTimeout(timeout);
|
|||
|
}, 3000);
|
|||
|
});
|
|||
|
$scrollTarget.on('scroll', function() {
|
|||
|
disabled || setState(null, scrolling);
|
|||
|
});
|
|||
|
$window.on('resize', window.throttle(function() {
|
|||
|
if (!disabled) {
|
|||
|
render(); calc(); setState(null, scrolling);
|
|||
|
}
|
|||
|
}, 100));
|
|||
|
}
|
|||
|
hasInit = true;
|
|||
|
}
|
|||
|
|
|||
|
setOptions(options);
|
|||
|
if (!disabled) {
|
|||
|
init();
|
|||
|
}
|
|||
|
$window.on('resize', window.throttle(function() {
|
|||
|
init();
|
|||
|
}, 200));
|
|||
|
return {
|
|||
|
setOptions: setOptions
|
|||
|
};
|
|||
|
}
|
|||
|
$.fn.toc = toc;
|
|||
|
});
|
|||
|
})();
|
|||
|
/*(function () {
|
|||
|
|
|||
|
})();*/
|
|||
|
</script><script>
|
|||
|
/* toc must before affix, since affix need to konw toc' height. */(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
var TOC_SELECTOR = window.TEXT_VARIABLES.site.toc.selectors;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
var $window = $(window);
|
|||
|
var $articleContent = $('.js-article-content');
|
|||
|
var $tocRoot = $('.js-toc-root'), $col2 = $('.js-col-aside');
|
|||
|
var toc;
|
|||
|
var tocDisabled = false;
|
|||
|
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
|
|||
|
var hasToc = $articleContent.find(TOC_SELECTOR).length > 0;
|
|||
|
|
|||
|
function disabled() {
|
|||
|
return $col2.css('display') === 'none' || !hasToc;
|
|||
|
}
|
|||
|
|
|||
|
tocDisabled = disabled();
|
|||
|
|
|||
|
toc = $tocRoot.toc({
|
|||
|
selectors: TOC_SELECTOR,
|
|||
|
container: $articleContent,
|
|||
|
scrollTarget: hasSidebar ? '.js-page-main' : null,
|
|||
|
scroller: hasSidebar ? '.js-page-main' : null,
|
|||
|
disabled: tocDisabled
|
|||
|
});
|
|||
|
|
|||
|
$window.on('resize', window.throttle(function() {
|
|||
|
tocDisabled = disabled();
|
|||
|
toc && toc.setOptions({
|
|||
|
disabled: tocDisabled
|
|||
|
});
|
|||
|
}, 100));
|
|||
|
|
|||
|
});
|
|||
|
})();
|
|||
|
(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
var $window = $(window), $pageFooter = $('.js-page-footer');
|
|||
|
var $pageAside = $('.js-page-aside');
|
|||
|
var affix;
|
|||
|
var tocDisabled = false;
|
|||
|
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
|
|||
|
|
|||
|
affix = $pageAside.affix({
|
|||
|
offsetBottom: $pageFooter.outerHeight(),
|
|||
|
scrollTarget: hasSidebar ? '.js-page-main' : null,
|
|||
|
scroller: hasSidebar ? '.js-page-main' : null,
|
|||
|
scroll: hasSidebar ? $('.js-page-main').children() : null,
|
|||
|
disabled: tocDisabled
|
|||
|
});
|
|||
|
|
|||
|
$window.on('resize', window.throttle(function() {
|
|||
|
affix && affix.setOptions({
|
|||
|
disabled: tocDisabled
|
|||
|
});
|
|||
|
}, 100));
|
|||
|
|
|||
|
window.pageAsideAffix = affix;
|
|||
|
});
|
|||
|
})();
|
|||
|
</script><!---->
|
|||
|
|
|||
|
</div>
|
|||
|
<script>(function () {
|
|||
|
var $root = document.getElementsByClassName('root')[0];
|
|||
|
if (window.hasEvent('touchstart')) {
|
|||
|
$root.dataset.isTouch = true;
|
|||
|
document.addEventListener('touchstart', function(){}, false);
|
|||
|
}
|
|||
|
})();
|
|||
|
</script>
|
|||
|
</body>
|
|||
|
</html>
|
|||
|
|