3405 lines
286 KiB
HTML
3405 lines
286 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>Nginx PHP MariaDB Nextcloud Hub - YannStatic</title>
|
|||
|
|
|||
|
<meta name="description" content="Nextcloud est une suite de logiciels client-serveur permettant de créer et d’utiliser des services d’hébergement de fichiers.">
|
|||
|
<link rel="canonical" href="https://static.rnmkcy.eu/2023/09/02/Nginx-PHP-MariaDB-Nextcloud_Hub.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;">Nginx PHP MariaDB Nextcloud Hub</h1></header></div><meta itemprop="headline" content="Nginx PHP MariaDB Nextcloud Hub"><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"> 2 sept. 2023</span>
|
|||
|
|
|||
|
<span title="Modification" style="color:#00FF7F">21 sept. 2024</span></li></ul></div><meta itemprop="datePublished" content="2024-09-21T00:00:00+02: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><p><em>Nextcloud est une suite de logiciels client-serveur permettant de créer et d’utiliser des services d’hébergement de fichiers.</em><br />
|
|||
|
<img src="/images/nextcloud-logo.png" alt="" height="150" /></p>
|
|||
|
|
|||
|
<p>Le nouveau design introduit avec les versions Nextcloud Hub repose sur 4 principes :</p>
|
|||
|
|
|||
|
<ol>
|
|||
|
<li>l’accent sur le contenu</li>
|
|||
|
<li>la facilité d’utilisation</li>
|
|||
|
<li>une plus grande accessibilité</li>
|
|||
|
<li>possibilité de s’approprier le design.</li>
|
|||
|
</ol>
|
|||
|
|
|||
|
<h1 id="nginx-php-mariadb-et-domaine">Nginx Php MariaDb et Domaine</h1>
|
|||
|
|
|||
|
<p><img src="/images/nginx-logo-a.png" alt="" height="60" /> <img src="/images/php8-logo.png" alt="" height="60" /> <img src="/images/mariadb-logo-a.png" alt="" height="60" /> <img src="/images/dns-logo-a.png" alt="" height="60" /></p>
|
|||
|
|
|||
|
<h2 id="nginx">Nginx</h2>
|
|||
|
|
|||
|
<p>https://techexpert.tips/fr/nginx-fr/</p>
|
|||
|
|
|||
|
<h3 id="paquet-nginx-extras">Paquet nginx-extras</h3>
|
|||
|
|
|||
|
<p>Nginx extras</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt install nginx-extras
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Si installation après compilation<br />
|
|||
|
<a href="https://www.abyssproject.net/2022/05/archivage-de-mon-script-de-build-nginx-et-comment-repasser-sous-nginx-extras/">Archivage de mon script de build NGINX (et comment repasser sous nginx-extras)</a></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># en mode su
|
|||
|
apt -o Dpkg::Options::="--force-confnew" install nginx-extras -y
|
|||
|
rm /usr/local/lib/x86_64-linux-gnu/perl/5.36.0/nginx.pm
|
|||
|
systemctl restart nginx
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Dans le cas d’une installation correcte, voici la structure</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/etc/nginx/
|
|||
|
├── conf.d
|
|||
|
├── fastcgi.conf
|
|||
|
├── fastcgi_params
|
|||
|
├── koi-utf
|
|||
|
├── koi-win
|
|||
|
├── mime.types
|
|||
|
├── modules-available
|
|||
|
├── modules-enabled
|
|||
|
│ ├── 10-mod-http-ndk.conf -> /usr/share/nginx/modules-available/mod-http-ndk.conf
|
|||
|
│ ├── 50-mod-http-auth-pam.conf -> /usr/share/nginx/modules-available/mod-http-auth-pam.conf
|
|||
|
│ ├── 50-mod-http-cache-purge.conf -> /usr/share/nginx/modules-available/mod-http-cache-purge.conf
|
|||
|
│ ├── 50-mod-http-dav-ext.conf -> /usr/share/nginx/modules-available/mod-http-dav-ext.conf
|
|||
|
│ ├── 50-mod-http-echo.conf -> /usr/share/nginx/modules-available/mod-http-echo.conf
|
|||
|
│ ├── 50-mod-http-fancyindex.conf -> /usr/share/nginx/modules-available/mod-http-fancyindex.conf
|
|||
|
│ ├── 50-mod-http-geoip2.conf -> /usr/share/nginx/modules-available/mod-http-geoip2.conf
|
|||
|
│ ├── 50-mod-http-geoip.conf -> /usr/share/nginx/modules-available/mod-http-geoip.conf
|
|||
|
│ ├── 50-mod-http-headers-more-filter.conf -> /usr/share/nginx/modules-available/mod-http-headers-more-filter.conf
|
|||
|
│ ├── 50-mod-http-image-filter.conf -> /usr/share/nginx/modules-available/mod-http-image-filter.conf
|
|||
|
│ ├── 50-mod-http-lua.conf -> /usr/share/nginx/modules-available/mod-http-lua.conf
|
|||
|
│ ├── 50-mod-http-perl.conf -> /usr/share/nginx/modules-available/mod-http-perl.conf
|
|||
|
│ ├── 50-mod-http-subs-filter.conf -> /usr/share/nginx/modules-available/mod-http-subs-filter.conf
|
|||
|
│ ├── 50-mod-http-uploadprogress.conf -> /usr/share/nginx/modules-available/mod-http-uploadprogress.conf
|
|||
|
│ ├── 50-mod-http-upstream-fair.conf -> /usr/share/nginx/modules-available/mod-http-upstream-fair.conf
|
|||
|
│ ├── 50-mod-http-xslt-filter.conf -> /usr/share/nginx/modules-available/mod-http-xslt-filter.conf
|
|||
|
│ ├── 50-mod-mail.conf -> /usr/share/nginx/modules-available/mod-mail.conf
|
|||
|
│ ├── 50-mod-nchan.conf -> /usr/share/nginx/modules-available/mod-nchan.conf
|
|||
|
│ ├── 50-mod-stream.conf -> /usr/share/nginx/modules-available/mod-stream.conf
|
|||
|
│ ├── 70-mod-stream-geoip2.conf -> /usr/share/nginx/modules-available/mod-stream-geoip2.conf
|
|||
|
│ └── 70-mod-stream-geoip.conf -> /usr/share/nginx/modules-available/mod-stream-geoip.conf
|
|||
|
├── nginx.conf
|
|||
|
├── proxy_params
|
|||
|
├── scgi_params
|
|||
|
├── sites-available
|
|||
|
│ └── default
|
|||
|
├── sites-enabled
|
|||
|
│ └── default -> /etc/nginx/sites-available/default
|
|||
|
├── snippets
|
|||
|
│ ├── fastcgi-php.conf
|
|||
|
│ └── snakeoil.conf
|
|||
|
├── uwsgi_params
|
|||
|
└── win-utf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Supprimer la configuration active par défaut et recharger nginx</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo rm /etc/nginx/sites-enabled/default
|
|||
|
sudo systemctl reload nginx
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Fichier /etc/nginx/nginx.conf</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> types_hash_max_size 2048;
|
|||
|
variables_hash_max_size 2048;
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="nginx-traitement-demande">nginx traitement demande</h3>
|
|||
|
|
|||
|
<h4 id="serveurs-virtuels-basés-sur-le-nom">Serveurs virtuels basés sur le nom</h4>
|
|||
|
|
|||
|
<p>nginx décide d’abord quel serveur doit traiter la requête. Commençons par une configuration simple où les trois serveurs virtuels écoutent sur le port *:80 :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
|
|||
|
listen 80;
|
|||
|
server_name example.org www.example.org;
|
|||
|
...
|
|||
|
}
|
|||
|
|
|||
|
server {
|
|||
|
listen 80;
|
|||
|
server_name example.net www.example.net;
|
|||
|
...
|
|||
|
}
|
|||
|
|
|||
|
server {
|
|||
|
listen 80;
|
|||
|
server_name example.com www.example.com;
|
|||
|
...
|
|||
|
}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Dans cette configuration, nginx teste uniquement le champ d’en-tête « Host » de la requête pour déterminer vers quel serveur la requête doit être acheminée.<br />
|
|||
|
Si sa valeur ne correspond à aucun nom de serveur ou si la requête ne contient pas du tout ce champ d’en-tête, alors nginx acheminera la requête vers le serveur par défaut pour ce port.<br />
|
|||
|
Dans la configuration ci-dessus, le serveur par défaut est le premier, ce qui correspond au comportement par défaut standard de nginx. Il peut également être défini explicitement quel serveur doit être par défaut, avec le paramètre <code class="language-plaintext highlighter-rouge">default_server</code> dans la directive d’écoute :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
|
|||
|
listen 80 default_server;
|
|||
|
server_name example.net www.example.net;
|
|||
|
...
|
|||
|
}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>Notez que le serveur par défaut est une propriété du port d’écoute et non du nom du serveur.</p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<h4 id="comment-empêcher-le-traitement-des-demandes-avec-des-noms-de-serveur-non-définis">Comment empêcher le traitement des demandes avec des noms de serveur non définis</h4>
|
|||
|
|
|||
|
<p>Si les requêtes sans le champ d’en-tête «Hosts» ne doivent pas être autorisées, un serveur qui supprime simplement les requêtes peut être défini :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
|
|||
|
listen 80;
|
|||
|
server_name "";
|
|||
|
return 444;
|
|||
|
}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ici, le nom du serveur est défini sur une chaîne vide qui correspondra aux requêtes sans le champ d’en-tête « Host », et un code non standard spécial nginx 444 est renvoyé pour fermer la connexion.</p>
|
|||
|
|
|||
|
<p class="info">Depuis la version 0.8.48, il s’agit du paramètre par défaut pour le nom du serveur, donc le server_name “” peut être omis. Dans les versions antérieures, le nom d’hôte de la machine était utilisé comme nom de serveur par défaut.</p>
|
|||
|
|
|||
|
<p><strong>Un code d’état 444</strong> indique généralement que le serveur n’a pas renvoyé de réponse au client et a fermé la connexion. Cela peut se produire pour plusieurs raisons, notamment</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>Le serveur ou le réseau peut rencontrer un problème temporaire ou permanent qui l’empêche de répondre à la demande du client.</li>
|
|||
|
<li>Le client peut avoir fait une demande que le serveur n’est pas en mesure de traiter ou qui enfreint les règles du serveur, ce qui amène ce dernier à mettre fin à la connexion.</li>
|
|||
|
<li>Un pare-feu ou un logiciel de sécurité peut bloquer la demande ou la réponse, ce qui entraîne la fermeture de la connexion sans réponse.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h4 id="serveurs-virtuels-mixtes-basés-sur-le-nom-et-basés-sur-ip">Serveurs virtuels mixtes basés sur le nom et basés sur IP</h4>
|
|||
|
|
|||
|
<p>Regardons une configuration plus complexe où certains serveurs virtuels écoutent sur différentes adresses :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
|
|||
|
listen 192.168.1.1:80;
|
|||
|
server_name example.org www.example.org;
|
|||
|
...
|
|||
|
}
|
|||
|
|
|||
|
server {
|
|||
|
listen 192.168.1.1:80;
|
|||
|
server_name example.net www.example.net;
|
|||
|
...
|
|||
|
}
|
|||
|
|
|||
|
server {
|
|||
|
listen 192.168.1.2:80;
|
|||
|
server_name example.com www.example.com;
|
|||
|
...
|
|||
|
}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Dans cette configuration, nginx teste d’abord l’adresse IP et le port de la requête par rapport aux directives d’écoute des blocs serveur . Il teste ensuite le champ d’en-tête « Host » de la requête par rapport aux entrées server_name des blocs de serveur qui correspondent à l’adresse IP et au port. Si le nom du serveur n’est pas trouvé, la requête sera traitée par le serveur par défaut. Par exemple, une requête www.example.com reçue sur le port 192.168.1.1:80 sera traitée par le serveur par défaut du port 192.168.1.1:80, c’est à dire par le premier serveur, puisqu’il n’y a pas de définition www.example.com pour ce port.</p>
|
|||
|
|
|||
|
<p>Comme déjà indiqué, un serveur par défaut est une propriété du port d’écoute, et différents serveurs par défaut peuvent être définis pour différents ports :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
|
|||
|
listen 192.168.1.1:80;
|
|||
|
server_name example.org www.example.org;
|
|||
|
...
|
|||
|
}
|
|||
|
|
|||
|
server {
|
|||
|
listen 192.168.1.1:80 default_server;
|
|||
|
server_name example.net www.example.net;
|
|||
|
...
|
|||
|
}
|
|||
|
|
|||
|
server {
|
|||
|
listen 192.168.1.2:80 default_server;
|
|||
|
server_name example.com www.example.com;
|
|||
|
...
|
|||
|
}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h4 id="une-configuration-simple-de-site-php">Une configuration simple de site PHP</h4>
|
|||
|
|
|||
|
<p>Voyons maintenant comment nginx choisit un emplacement pour traiter une demande pour un site PHP simple et typique :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
|
|||
|
listen 80;
|
|||
|
server_name example.org www.example.org;
|
|||
|
root /data/www;
|
|||
|
|
|||
|
location / {
|
|||
|
index index.html index.php;
|
|||
|
}
|
|||
|
|
|||
|
location ~* \.(gif|jpg|png)$ {
|
|||
|
expires 30d;
|
|||
|
}
|
|||
|
|
|||
|
location ~ \.php$ {
|
|||
|
fastcgi_pass localhost:9000;
|
|||
|
fastcgi_param SCRIPT_FILENAME
|
|||
|
$document_root$fastcgi_script_name;
|
|||
|
include fastcgi_params;
|
|||
|
}
|
|||
|
}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>nginx recherche d’abord l’emplacement de préfixe le plus spécifique donné par les chaînes littérales, quel que soit l’ordre indiqué. Dans la configuration ci-dessus, le seul emplacement du préfixe est «/ » et comme il correspond à toute demande, il sera utilisé en dernier recours. Ensuite, nginx vérifie les emplacements donnés par l’expression régulière dans l’ordre indiqué dans le fichier de configuration. La première expression correspondante arrête la recherche et nginx utilisera cet emplacement. Si aucune expression régulière ne correspond à une requête, nginx utilise l’emplacement de préfixe le plus spécifique trouvé précédemment.</p>
|
|||
|
|
|||
|
<p>Notez que les emplacements de tous types testent uniquement une partie URI de la ligne de requête sans arguments. Cela est dû au fait que les arguments dans la chaîne de requête peuvent être donnés de plusieurs manières, par exemple :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/index.php?user=john&page=1
|
|||
|
/index.php?page=1&user=john
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>De plus, n’importe qui peut demander n’importe quoi dans la chaîne de requête :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/index.php?page=1&something+else&user=john
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Voyons maintenant comment les requêtes seraient traitées dans la configuration ci-dessus :</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
<table>
|
|||
|
<tbody>
|
|||
|
<tr>
|
|||
|
<td>Une requête «/logo.gif » correspond /d’abord à l’emplacement du préfixe « », puis à l’expression régulière «.(gif</td>
|
|||
|
<td>jpg</td>
|
|||
|
<td>png)$ », elle est donc traitée par ce dernier emplacement. À l’aide de la directive «root /data/www », la demande est mappée au fichier /data/www/logo.gifet le fichier est envoyé au client.</td>
|
|||
|
</tr>
|
|||
|
</tbody>
|
|||
|
</table>
|
|||
|
</li>
|
|||
|
<li>Une requête «/index.php » correspond également /d’abord à l’emplacement du préfixe « », puis à l’expression régulière «.(php)$ ». Par conséquent, elle est gérée par ce dernier emplacement et la requête est transmise à un serveur FastCGI écoutant sur localhost:9000. La directive fastcgi_param définit le paramètre FastCGI SCRIPT_FILENAMEsur «/data/www/index.php » et le serveur FastCGI exécute le fichier. La variable $document_rootest égale à la valeur de la directive racine et la variable $fastcgi_script_nameest égale à l’URI de la requête, c’est à dire «/index.php ».</li>
|
|||
|
<li>Une requête «/about.html » correspond /uniquement à l’emplacement du préfixe « » ; elle est donc traitée à cet emplacement. À l’aide de la directive «root /data/www », la demande est mappée au fichier /data/www/about.htmlet le fichier est envoyé au client.</li>
|
|||
|
<li>Le traitement d’une requête «/ » est plus complexe. Il correspond uniquement au préfixe d’emplacement «/ » et est donc géré par cet emplacement. Ensuite, la directive index teste l’existence de fichiers d’index en fonction de ses paramètres et de la root /data/wwwdirective « ». Si le fichier /data/www/index.htmln’existe pas et que le fichier /data/www/index.phpexiste, alors la directive effectue une redirection interne vers «/index.php » et nginx recherche à nouveau les emplacements comme si la demande avait été envoyée par un client. Comme nous l’avons vu précédemment, la requête redirigée sera finalement traitée par le serveur FastCGI.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h2 id="php">PHP</h2>
|
|||
|
|
|||
|
<p>Pour installer la version de 8 de php, ajouter le dépôt sury.</p>
|
|||
|
|
|||
|
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt <span class="nb">install</span> <span class="nt">-y</span> lsb-release apt-transport-https ca-certificates wget
|
|||
|
<span class="nb">sudo </span>wget <span class="nt">-O</span> /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
|
|||
|
<span class="nb">echo</span> <span class="s2">"deb https://packages.sury.org/php/ </span><span class="si">$(</span>lsb_release <span class="nt">-sc</span><span class="si">)</span><span class="s2"> main"</span> |sudo <span class="nb">tee</span> /etc/apt/sources.list.d/php.list
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Mise à jour des dépôts :</p>
|
|||
|
|
|||
|
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt update <span class="o">&&</span> <span class="nb">sudo </span>apt upgrade <span class="nt">-y</span>
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="php83">PHP8.3</h3>
|
|||
|
|
|||
|
<p>Installation</p>
|
|||
|
|
|||
|
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt <span class="nt">-y</span> <span class="nb">install </span>php8.3 php8.3-fpm php8.3-sqlite3 php8.3-cli php8.3-gd php8.3-imap php8.3-mysql php8.3-soap php8.3-apcu php8.3-common php8.3-gmp php8.3-intl php8.3-opcache php8.3-xml php8.3-curl php8.3-igbinary php8.3-readline php8.3-zip php8.3-bcmath php8.3-imagick php8.3-mbstring php8.3-redis imagemagick libmagickcore-6.q16-6-extra php8.3-bz2 php8.3-smbclient
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><u>Le fichier php.ini CLI (Command Line Interface) est la configuration PHP qui s'applique lorsque vous exécutez des scripts PHP en ligne de commande</u>.(<a href="https://www.larevuegeek.com/articles/actualites-nextcloud-corrigier-lerreur-memcache-oc-memcache-apcu-not-available-for-local-cache-article643.html">Nextcloud : Corrigier l’erreur Memcache \OC\Memcache\APCu not available for local cache</a>)<br />
|
|||
|
Pour assurer le fonctionnement optimal de Nextcloud, il peut être nécessaire d’activer l’extension APCu dans ce fichier.(en mode su)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo "apc.enable_cli = 1" >> /etc/php/8.3/cli/php.ini
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="mariadb">MariaDB</h2>
|
|||
|
|
|||
|
<p>Installer MariaDB :</p>
|
|||
|
|
|||
|
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt <span class="nb">install </span>mariadb-server
|
|||
|
<span class="nb">sudo </span>mysql_secure_installation <span class="c"># Y à tout et nouveau mot de passe n</span>
|
|||
|
</code></pre></div></div>
|
|||
|
<p>Base ‘nextcloud’ , en mode su</p>
|
|||
|
|
|||
|
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">MOTPASSEDB</span><span class="o">=</span><span class="s2">"uXbPk3b2wG8llQl"</span>
|
|||
|
mysql <span class="nt">-uroot</span> <span class="nt">-e</span> <span class="s2">"CREATE DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; </span><span class="se">\</span><span class="s2">
|
|||
|
CREATE USER 'nextcloud'@'localhost' IDENTIFIED BY '</span><span class="nv">$MOTPASSEDB</span><span class="s2">'; </span><span class="se">\</span><span class="s2">
|
|||
|
GRANT ALL PRIVILEGES ON nextcloud.* TO 'nextcloud'@'localhost' IDENTIFIED BY '</span><span class="nv">$MOTPASSEDB</span><span class="s2">'; FLUSH PRIVILEGES;"</span>
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Pour info<br />
|
|||
|
Effacer une base : <code class="language-plaintext highlighter-rouge">mysql -uroot -e 'DROP DATABASE nextcloud'</code><br />
|
|||
|
Effacer un utilisateur : <code class="language-plaintext highlighter-rouge">mysql -uroot -e 'DROP USER "nextcloud"@"localhost";'</code></p>
|
|||
|
|
|||
|
<h2 id="sous-domaine-et-certificats">Sous-Domaine et certificats</h2>
|
|||
|
|
|||
|
<p><a href="/2017/08/31/Acme-Certficats-Serveurs.html">Serveur , installer et renouveler les certificats SSL Let’s encrypt via Acme</a><br />
|
|||
|
Disposer d’un sous-domaine (ici cloud.rnmkcy.eu) avec des certficats SSL valides (Let’s Encrypt)</p>
|
|||
|
|
|||
|
<h2 id="nextcloud-hub">Nextcloud Hub</h2>
|
|||
|
|
|||
|
<p><img src="/images/nextcloud_logo_128px.png" alt="" /><br />
|
|||
|
<a href="https://docs.nextcloud.com/server/latest/user_manual/fr/">Manuel utilisateur Nextcloud</a></p>
|
|||
|
|
|||
|
<p><em>Référence: <a href="https://nextcloud.com/install/">Nextcloud Install</a></em></p>
|
|||
|
|
|||
|
<h3 id="dernière-version-nextcloud">Dernière version Nextcloud</h3>
|
|||
|
|
|||
|
<p>en mode super utilisateur</p>
|
|||
|
|
|||
|
<p>Lien des versions Nextcloud server <a href="https://download.nextcloud.com/server/releases/">https://download.nextcloud.com/server/releases/</a><br />
|
|||
|
On choisit “latest” dans la version<br />
|
|||
|
<img src="/images/nextcloud-latest.png" alt="" /></p>
|
|||
|
|
|||
|
<p>Installer</p>
|
|||
|
|
|||
|
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># mode su</span>
|
|||
|
wget https://download.nextcloud.com/server/releases/latest.tar.bz2
|
|||
|
<span class="c"># checksum et vérification</span>
|
|||
|
<span class="c">#wget https://download.nextcloud.com/server/releases/latest.tar.bz2.sha256</span>
|
|||
|
<span class="c">#sha256sum -c latest.tar.bz2.sha256 < latest.tar.bz2 </span>
|
|||
|
<span class="c"># Décompression, déplacement et effacement</span>
|
|||
|
<span class="nb">tar</span> <span class="nt">-xvf</span> latest.tar.bz2
|
|||
|
<span class="nb">mv </span>nextcloud /var/www/
|
|||
|
<span class="nb">rm </span>latest.tar.bz2
|
|||
|
<span class="c"># Utilisateur nextcloud et droits</span>
|
|||
|
useradd <span class="nt">-r</span> nextcloud
|
|||
|
<span class="nb">chown</span> <span class="nt">-R</span> nextcloud:www-data /var/www/nextcloud
|
|||
|
<span class="nb">chmod</span> <span class="nt">-R</span> o-rwx /var/www/nextcloud
|
|||
|
<span class="c"># Nextcloud data</span>
|
|||
|
<span class="nb">mkdir</span> <span class="nt">-p</span> /srv/nextcloud-data/
|
|||
|
<span class="nb">chown</span> <span class="nt">-R</span> nextcloud:nextcloud /srv/nextcloud-data/
|
|||
|
<span class="nb">chmod</span> <span class="nt">-R</span> o-rwx /srv/nextcloud-data/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="pool-php-fpm-nextcloud">Pool PHP-FPM Nextcloud</h3>
|
|||
|
|
|||
|
<p><u>Pool PHP-FPM 8.3</u> Nextcloud : <code class="language-plaintext highlighter-rouge">/etc/php/8.3/fpm/pool.d/nextcloud.conf</code><br />
|
|||
|
en mode su</p>
|
|||
|
|
|||
|
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> <span class="o">></span> /etc/php/8.3/fpm/pool.d/nextcloud.conf <span class="o"><<</span> <span class="no">EOF</span><span class="sh">
|
|||
|
[nextcloud]
|
|||
|
|
|||
|
user = nextcloud
|
|||
|
group = nextcloud
|
|||
|
|
|||
|
chdir = /var/www/nextcloud
|
|||
|
|
|||
|
listen = /var/run/php/php8.3-fpm-nextcloud.sock
|
|||
|
listen.owner = www-data
|
|||
|
listen.group = www-data
|
|||
|
|
|||
|
pm = dynamic
|
|||
|
pm.max_children = 16
|
|||
|
pm.max_requests = 500
|
|||
|
request_terminate_timeout = 1d
|
|||
|
|
|||
|
|
|||
|
pm.start_servers = 6
|
|||
|
pm.min_spare_servers = 5
|
|||
|
pm.max_spare_servers = 8
|
|||
|
|
|||
|
|
|||
|
; Additional php.ini defines, specific to this pool of workers.
|
|||
|
env[PATH] = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
|||
|
php_admin_value[memory_limit] = 512M
|
|||
|
php_value[upload_max_filesize] = 10G
|
|||
|
php_value[post_max_size] = 10G
|
|||
|
php_value[default_charset] = UTF-8
|
|||
|
; OPcache is already activated by default
|
|||
|
; php_value[opcache.enable]=1
|
|||
|
; The following parameters are nevertheless recommended for Nextcloud
|
|||
|
; see here: https://docs.nextcloud.com/server/15/admin_manual/installation/server_tuning.html#enable-php-opcache
|
|||
|
php_value[opcache.enable_cli]=1
|
|||
|
php_value[opcache.interned_strings_buffer]=16
|
|||
|
php_value[opcache.max_accelerated_files]=10000
|
|||
|
php_value[opcache.memory_consumption]=512
|
|||
|
php_value[opcache.save_comments]=1
|
|||
|
php_value[opcache.revalidate_freq]=60
|
|||
|
; https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/caching_configuration.html#id1
|
|||
|
php_value[apc.enabled]=1
|
|||
|
php_value[apc.enable_cli]=1
|
|||
|
</span><span class="no">EOF
|
|||
|
</span></code></pre></div></div>
|
|||
|
|
|||
|
<p>Avec ldap</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt install php8.3-ldap
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Relancer le service</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl restart php8.3-fpm
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="nextcloud-nginx-headerssslhstsocsp">Nextcloud Nginx headers,SSL,HSTS,OCSP</h3>
|
|||
|
|
|||
|
<p><a href="/2022/10/22/Nginx_headers_SSL_HSTS_OCSP.html">Nginx headers,SSL,HSTS,OCSP</a></p>
|
|||
|
|
|||
|
<p>Versions<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">nginx -v</code> : nginx version: nginx/1.22.1<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">openssl version</code> : OpenSSL 3.0.13 30 Jan 2024 (Library: OpenSSL 3.0.13 30 Jan 2024)<br />
|
|||
|
<a href="https://ssl-config.mozilla.org/#server=nginx&version=1.24.0&config=modern&openssl=1.1.1n&guideline=5.7">SSL Configuration Generator</a></p>
|
|||
|
|
|||
|
<p>Créer en conséquence le fichier le fichier <code class="language-plaintext highlighter-rouge">/etc/nginx/conf.d/security.conf.inc</code> ci-dessous suivant le résultat de la requête précédente</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> ssl_certificate /etc/ssl/private/rnmkcy.eu-fullchain.pem;
|
|||
|
ssl_certificate_key /etc/ssl/private/rnmkcy.eu-key.pem;
|
|||
|
ssl_session_timeout 1d;
|
|||
|
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
|
|||
|
ssl_session_tickets off;
|
|||
|
|
|||
|
# modern configuration
|
|||
|
ssl_protocols TLSv1.3;
|
|||
|
ssl_prefer_server_ciphers off;
|
|||
|
|
|||
|
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
|
|||
|
#add_header Strict-Transport-Security "max-age=63072000" always;
|
|||
|
|
|||
|
# OCSP stapling
|
|||
|
ssl_stapling on;
|
|||
|
ssl_stapling_verify on;
|
|||
|
|
|||
|
# verify chain of trust of OCSP response using Root CA and Intermediate certs
|
|||
|
ssl_trusted_certificate /etc/ssl/private/rnmkcy.eu-fullchain.pem;
|
|||
|
|
|||
|
# replace with the IP address of your resolver
|
|||
|
resolver 1.1.1.1 9.9.9.9 valid=300s;
|
|||
|
resolver_timeout 5s;
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Si vous avez installé un résolveur en local , remplacer <code class="language-plaintext highlighter-rouge">1.1.1.1 9.9.9.9</code> par <code class="language-plaintext highlighter-rouge">127.0.0.1</code><br />
|
|||
|
Remplacer rnmkcy.eu par le nom du domaine souhaité</p>
|
|||
|
|
|||
|
<h3 id="nextcloud-vhost-nginx">Nextcloud Vhost nginx</h3>
|
|||
|
|
|||
|
<p>Nexcloud sur le domaine cloud.domain.tld avec certificats Let’s Encrypt</p>
|
|||
|
|
|||
|
<p><code class="language-plaintext warning highlighter-rouge">ATTENTION !!! Remplacer domain.tld par le nom de votre domaine</code></p>
|
|||
|
|
|||
|
<p>Le fichier de configuration web cloud.domain.tld.conf <code class="language-plaintext highlighter-rouge">/etc/nginx/conf.d/cloud.domain.tld.conf</code></p>
|
|||
|
|
|||
|
<details>
|
|||
|
<summary><b>Etendre Réduire cloud.domain.tld.conf</b></summary>
|
|||
|
|
|||
|
|
|||
|
<figure class="highlight"><pre><code class="language-nginx" data-lang="nginx">
|
|||
|
<span class="k">upstream</span> <span class="s">php-handler</span> <span class="p">{</span>
|
|||
|
<span class="c1">#server 127.0.0.1:9000;</span>
|
|||
|
<span class="c1">#server unix:/var/run/php/php8.2-fpm-nextcloud.sock;</span>
|
|||
|
<span class="kn">server</span> <span class="s">unix:/var/run/php/php8.3-fpm-nextcloud.sock</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="k">server</span> <span class="p">{</span>
|
|||
|
<span class="kn">listen</span> <span class="mi">80</span><span class="p">;</span>
|
|||
|
<span class="kn">listen</span> <span class="s">[::]:80</span><span class="p">;</span>
|
|||
|
<span class="kn">server_name</span> <span class="s">cloud.rnmkcy.eu</span><span class="p">;</span>
|
|||
|
<span class="c1"># enforce https</span>
|
|||
|
<span class="kn">return</span> <span class="mi">301</span> <span class="s">https://</span><span class="nv">$server_name</span><span class="p">:</span><span class="mi">443</span><span class="nv">$request_uri</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="k">server</span> <span class="p">{</span>
|
|||
|
<span class="kn">listen</span> <span class="mi">443</span> <span class="s">ssl</span> <span class="s">http2</span><span class="p">;</span>
|
|||
|
<span class="kn">listen</span> <span class="s">[::]:443</span> <span class="s">ssl</span> <span class="s">http2</span><span class="p">;</span>
|
|||
|
<span class="kn">server_name</span> <span class="s">cloud.rnmkcy.eu</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="kn">include</span> <span class="n">/etc/nginx/conf.d/security.conf.inc</span><span class="p">;</span>
|
|||
|
<span class="kn">more_set_headers</span> <span class="s">"Strict-Transport-Security</span> <span class="p">:</span> <span class="s">max-age=63072000</span><span class="p">;</span> <span class="kn">includeSubDomains</span><span class="p">;</span> <span class="kn">preload"</span><span class="p">;</span>
|
|||
|
|
|||
|
|
|||
|
<span class="c1"># include snippets/authelia-location.conf; # Authelia auth endpoint</span>
|
|||
|
|
|||
|
|
|||
|
<span class="kn">location</span> <span class="s">^~</span> <span class="n">/.well-known</span> <span class="p">{</span>
|
|||
|
<span class="c1"># The following 6 rules are borrowed from `.htaccess`</span>
|
|||
|
|
|||
|
<span class="c1"># The following 2 rules are only needed for the user_webfinger app.</span>
|
|||
|
<span class="c1"># Uncomment it if you're planning to use this app.</span>
|
|||
|
<span class="c1">#rewrite ^/\.well-known/host-meta\.json /public.php?service=host-meta-json last;</span>
|
|||
|
<span class="c1">#rewrite ^/\.well-known/host-meta /public.php?service=host-meta last;</span>
|
|||
|
|
|||
|
<span class="kn">location</span> <span class="p">=</span> <span class="n">/.well-known/carddav</span> <span class="p">{</span> <span class="kn">return</span> <span class="mi">301</span> <span class="n">/remote.php/dav/</span><span class="p">;</span> <span class="p">}</span>
|
|||
|
<span class="kn">location</span> <span class="p">=</span> <span class="n">/.well-known/caldav</span> <span class="p">{</span> <span class="kn">return</span> <span class="mi">301</span> <span class="n">/remote.php/dav/</span><span class="p">;</span> <span class="p">}</span>
|
|||
|
|
|||
|
<span class="kn">location</span> <span class="p">=</span> <span class="n">/.well-known/webfinger</span> <span class="p">{</span> <span class="kn">return</span> <span class="mi">301</span> <span class="n">/index.php</span><span class="nv">$uri</span><span class="p">;</span> <span class="p">}</span>
|
|||
|
<span class="kn">location</span> <span class="p">=</span> <span class="n">/.well-known/nodeinfo</span> <span class="p">{</span> <span class="kn">return</span> <span class="mi">301</span> <span class="n">/index.php</span><span class="nv">$uri</span><span class="p">;</span> <span class="p">}</span>
|
|||
|
|
|||
|
<span class="kn">try_files</span> <span class="nv">$uri</span> <span class="nv">$uri</span><span class="n">/</span> <span class="p">=</span><span class="mi">404</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="c1">#sub_path_only rewrite ^/$ / permanent;</span>
|
|||
|
<span class="kn">location</span> <span class="s">^~</span> <span class="n">/</span> <span class="p">{</span>
|
|||
|
|
|||
|
<span class="c1"># Path to source</span>
|
|||
|
<span class="kn">alias</span> <span class="n">/var/www/nextcloud/</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="c1"># Set max upload size</span>
|
|||
|
<span class="kn">client_max_body_size</span> <span class="mi">10G</span><span class="p">;</span>
|
|||
|
<span class="kn">fastcgi_buffers</span> <span class="mi">64</span> <span class="mi">4K</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="c1"># Enable gzip but do not remove ETag headers</span>
|
|||
|
<span class="kn">gzip</span> <span class="no">on</span><span class="p">;</span>
|
|||
|
<span class="kn">gzip_vary</span> <span class="no">on</span><span class="p">;</span>
|
|||
|
<span class="kn">gzip_comp_level</span> <span class="mi">4</span><span class="p">;</span>
|
|||
|
<span class="kn">gzip_min_length</span> <span class="mi">256</span><span class="p">;</span>
|
|||
|
<span class="kn">gzip_proxied</span> <span class="s">expired</span> <span class="s">no-cache</span> <span class="s">no-store</span> <span class="s">private</span> <span class="s">no_last_modified</span> <span class="s">no_etag</span> <span class="s">auth</span><span class="p">;</span>
|
|||
|
<span class="kn">gzip_types</span> <span class="nc">application/atom</span><span class="s">+xml</span> <span class="nc">application/javascript</span> <span class="nc">application/json</span> <span class="nc">application/ld</span><span class="s">+json</span> <span class="nc">application/manifest</span><span class="s">+json</span> <span class="nc">application/rss</span><span class="s">+xml</span> <span class="nc">application/vnd</span><span class="s">.geo+json</span> <span class="nc">application/vnd</span><span class="s">.ms-fontobject</span> <span class="nc">application/x-font-ttf</span> <span class="nc">application/x-web-app-manifest</span><span class="s">+json</span> <span class="nc">application/xhtml</span><span class="s">+xml</span> <span class="nc">application/xml</span> <span class="nc">font/opentype</span> <span class="nc">image/bmp</span> <span class="nc">image/svg</span><span class="s">+xml</span> <span class="nc">image/x-icon</span> <span class="nc">text/cache-manifest</span> <span class="nc">text/css</span> <span class="nc">text/plain</span> <span class="nc">text/vcard</span> <span class="nc">text/vnd</span><span class="s">.rim.location.xloc</span> <span class="nc">text/vtt</span> <span class="nc">text/x-component</span> <span class="nc">text/x-cross-domain-policy</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="c1"># Pagespeed is not supported by Nextcloud, so if your server is built</span>
|
|||
|
<span class="c1"># with the `ngx_pagespeed` module, uncomment this line to disable it.</span>
|
|||
|
<span class="c1">#pagespeed off;</span>
|
|||
|
|
|||
|
<span class="c1"># The settings allows you to optimize the HTTP2 bandwitdth.</span>
|
|||
|
<span class="c1"># See https://blog.cloudflare.com/delivering-http-2-upload-speed-improvements/</span>
|
|||
|
<span class="c1"># for tunning hints</span>
|
|||
|
<span class="kn">client_body_buffer_size</span> <span class="mi">512k</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="c1"># HTTP response headers borrowed from Nextcloud `.htaccess`</span>
|
|||
|
<span class="c1">#more_set_headers "Strict-Transport-Security: max-age=15768000; includeSubDomains; preload;";</span>
|
|||
|
<span class="kn">more_set_headers</span> <span class="s">"Referrer-Policy:</span> <span class="s">no-referrer"</span><span class="p">;</span>
|
|||
|
<span class="kn">more_set_headers</span> <span class="s">"X-Content-Type-Options:</span> <span class="s">nosniff"</span><span class="p">;</span>
|
|||
|
<span class="kn">more_set_headers</span> <span class="s">"X-Download-Options:</span> <span class="s">noopen"</span><span class="p">;</span>
|
|||
|
<span class="kn">more_set_headers</span> <span class="s">"X-Frame-Options:</span> <span class="s">SAMEORIGIN"</span><span class="p">;</span>
|
|||
|
<span class="kn">more_set_headers</span> <span class="s">"X-Permitted-Cross-Domain-Policies:</span> <span class="s">none"</span><span class="p">;</span>
|
|||
|
<span class="kn">more_set_headers</span> <span class="s">"X-Robots-Tag:</span> <span class="s">noindex,</span> <span class="s">nofollow"</span><span class="p">;</span>
|
|||
|
<span class="kn">more_set_headers</span> <span class="s">"X-XSS-Protection:</span> <span class="mi">1</span><span class="p">;</span> <span class="kn">mode=block"</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="c1"># Remove X-Powered-By, which is an information leak</span>
|
|||
|
<span class="kn">fastcgi_hide_header</span> <span class="s">X-Powered-By</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="c1"># Specify how to handle directories -- specifying `/nextcloud/index.php$request_uri`</span>
|
|||
|
<span class="c1"># here as the fallback means that Nginx always exhibits the desired behaviour</span>
|
|||
|
<span class="c1"># when a client requests a path that corresponds to a directory that exists</span>
|
|||
|
<span class="c1"># on the server. In particular, if that directory contains an index.php file,</span>
|
|||
|
<span class="c1"># that file is correctly served; if it doesn't, then the request is passed to</span>
|
|||
|
<span class="c1"># the front-end controller. This consistent behaviour means that we don't need</span>
|
|||
|
<span class="c1"># to specify custom rules for certain paths (e.g. images and other assets,</span>
|
|||
|
<span class="c1"># `/updater`, `/ocm-provider`, `/ocs-provider`), and thus</span>
|
|||
|
<span class="c1"># `try_files $uri $uri/ /nextcloud/index.php$request_uri`</span>
|
|||
|
<span class="c1"># always provides the desired behaviour.</span>
|
|||
|
<span class="kn">index</span> <span class="s">index.php</span> <span class="s">index.html</span> <span class="n">/index.php</span><span class="nv">$request_uri</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="c1"># Rule borrowed from `.htaccess` to handle Microsoft DAV clients</span>
|
|||
|
<span class="kn">location</span> <span class="p">=</span> <span class="n">/</span> <span class="p">{</span>
|
|||
|
<span class="kn">if</span> <span class="s">(</span> <span class="nv">$http_user_agent</span> <span class="p">~</span> <span class="sr">^DavClnt</span> <span class="s">)</span> <span class="p">{</span>
|
|||
|
<span class="kn">return</span> <span class="mi">302</span> <span class="n">/remote.php/webdav/</span><span class="nv">$is_args$args</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="kn">location</span> <span class="p">=</span> <span class="n">/robots.txt</span> <span class="p">{</span>
|
|||
|
<span class="kn">allow</span> <span class="s">all</span><span class="p">;</span>
|
|||
|
<span class="kn">log_not_found</span> <span class="no">off</span><span class="p">;</span>
|
|||
|
<span class="kn">access_log</span> <span class="no">off</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="c1"># Rules borrowed from `.htaccess` to hide certain paths from clients</span>
|
|||
|
<span class="kn">location</span> <span class="p">~</span> <span class="sr">^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)</span> <span class="p">{</span> <span class="kn">return</span> <span class="mi">404</span><span class="p">;</span> <span class="p">}</span>
|
|||
|
<span class="kn">location</span> <span class="p">~</span> <span class="sr">^/(?:\.|autotest|occ|issue|indie|db_|console)</span> <span class="p">{</span> <span class="kn">return</span> <span class="mi">404</span><span class="p">;</span> <span class="p">}</span>
|
|||
|
|
|||
|
<span class="c1"># Ensure this block, which passes PHP files to the PHP process, is above the blocks</span>
|
|||
|
<span class="c1"># which handle static assets (as seen below). If this block is not declared first,</span>
|
|||
|
<span class="c1"># then Nginx will encounter an infinite rewriting loop when it prepends</span>
|
|||
|
<span class="c1"># `/nextcloud/index.php` to the URI, resulting in a HTTP 500 error response.</span>
|
|||
|
<span class="kn">location</span> <span class="p">~</span> <span class="sr">\.php(?:$|/)</span> <span class="p">{</span>
|
|||
|
<span class="c1"># Required for legacy support</span>
|
|||
|
<span class="kn">rewrite</span> <span class="s">^/(?!index|remote|public|cron|core</span><span class="err">\</span><span class="n">/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode\/proxy|.+\/richdocumentscode_arm64\/proxy</span><span class="s">)</span> <span class="n">/index.php</span><span class="nv">$request_uri</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="kn">fastcgi_split_path_info</span> <span class="s">^(.+?</span><span class="err">\</span><span class="s">.php)(/.*)</span>$<span class="p">;</span>
|
|||
|
<span class="kn">set</span> <span class="nv">$path_info</span> <span class="nv">$fastcgi_path_info</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="kn">try_files</span> <span class="nv">$fastcgi_script_name</span> <span class="p">=</span><span class="mi">404</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="kn">include</span> <span class="s">fastcgi_params</span><span class="p">;</span>
|
|||
|
<span class="kn">fastcgi_param</span> <span class="s">SCRIPT_FILENAME</span> <span class="nv">$request_filename</span><span class="p">;</span>
|
|||
|
<span class="kn">fastcgi_split_path_info</span> <span class="s">^(.+</span><span class="err">\</span><span class="s">.php)(/.+)</span>$<span class="p">;</span>
|
|||
|
<span class="kn">fastcgi_param</span> <span class="s">HTTPS</span> <span class="no">on</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="kn">fastcgi_param</span> <span class="s">modHeadersAvailable</span> <span class="s">true</span><span class="p">;</span> <span class="c1"># Avoid sending the security headers twice</span>
|
|||
|
<span class="kn">fastcgi_param</span> <span class="s">front_controller_active</span> <span class="s">true</span><span class="p">;</span> <span class="c1"># Enable pretty urls</span>
|
|||
|
<span class="kn">fastcgi_param</span> <span class="s">HTTP_ACCEPT_ENCODING</span> <span class="s">""</span><span class="p">;</span> <span class="c1"># Disable encoding of nextcloud response to inject ynh scripts</span>
|
|||
|
<span class="kn">fastcgi_pass</span> <span class="s">php-handler</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="kn">fastcgi_intercept_errors</span> <span class="no">on</span><span class="p">;</span>
|
|||
|
<span class="kn">fastcgi_request_buffering</span> <span class="no">off</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="kn">fastcgi_read_timeout</span> <span class="mi">600</span><span class="p">;</span>
|
|||
|
<span class="kn">fastcgi_send_timeout</span> <span class="mi">600</span><span class="p">;</span>
|
|||
|
<span class="kn">fastcgi_connect_timeout</span> <span class="mi">600</span><span class="p">;</span>
|
|||
|
<span class="kn">proxy_connect_timeout</span> <span class="mi">600</span><span class="p">;</span>
|
|||
|
<span class="kn">proxy_send_timeout</span> <span class="mi">600</span><span class="p">;</span>
|
|||
|
<span class="kn">proxy_read_timeout</span> <span class="mi">600</span><span class="p">;</span>
|
|||
|
<span class="kn">send_timeout</span> <span class="mi">600</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="kn">location</span> <span class="p">~</span> <span class="sr">^/(?:updater|ocs-provider)(?:$|/)</span> <span class="p">{</span>
|
|||
|
<span class="kn">try_files</span> <span class="nv">$uri</span><span class="n">/</span> <span class="p">=</span><span class="mi">404</span><span class="p">;</span>
|
|||
|
<span class="kn">index</span> <span class="s">index.php</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="c1"># Serve static files</span>
|
|||
|
<span class="kn">location</span> <span class="p">~</span> <span class="sr">\.(?:css|js|mjs|svg|gif|png|jpg|ico|wasm|tflite|map)$</span> <span class="p">{</span>
|
|||
|
<span class="kn">try_files</span> <span class="nv">$uri</span> <span class="n">/</span> <span class="n">/index.php</span><span class="nv">$request_uri</span><span class="p">;</span>
|
|||
|
<span class="kn">expires</span> <span class="mi">6M</span><span class="p">;</span> <span class="c1"># Cache-Control policy borrowed from `.htaccess`</span>
|
|||
|
<span class="kn">access_log</span> <span class="no">off</span><span class="p">;</span> <span class="c1"># Optional: Don't log access to assets</span>
|
|||
|
|
|||
|
<span class="kn">location</span> <span class="p">~</span> <span class="sr">\.wasm$</span> <span class="p">{</span>
|
|||
|
<span class="kn">default_type</span> <span class="nc">application/wasm</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="kn">location</span> <span class="p">~</span> <span class="sr">\.woff2?$</span> <span class="p">{</span>
|
|||
|
<span class="kn">try_files</span> <span class="nv">$uri</span> <span class="n">/</span> <span class="n">/index.php</span><span class="nv">$request_uri</span><span class="p">;</span>
|
|||
|
<span class="kn">expires</span> <span class="s">7d</span><span class="p">;</span> <span class="c1"># Cache-Control policy borrowed from `.htaccess`</span>
|
|||
|
<span class="kn">access_log</span> <span class="no">off</span><span class="p">;</span> <span class="c1"># Optional: Don't log access to assets</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="c1"># Rule borrowed from `.htaccess`</span>
|
|||
|
<span class="kn">location</span> <span class="n">/remote</span> <span class="p">{</span>
|
|||
|
<span class="kn">return</span> <span class="mi">301</span> <span class="n">/remote.php</span><span class="nv">$request_uri</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="kn">location</span> <span class="p">~</span> <span class="sr">/</span> <span class="p">{</span>
|
|||
|
<span class="kn">if</span> <span class="s">(</span><span class="nv">$request_method</span> <span class="p">~</span> <span class="sr">^(PUT|DELETE|PATCH|PROPFIND|PROPPATCH)$)</span> <span class="p">{</span>
|
|||
|
<span class="kn">rewrite</span> <span class="s">^</span> <span class="n">/index.php</span><span class="nv">$request_uri</span> <span class="s">last</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
<span class="kn">try_files</span> <span class="nv">$uri</span> <span class="n">/</span> <span class="n">/index.php</span><span class="nv">$request_uri</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
<span class="c1"># include snippets/authelia-authrequest.conf; # Protect this endpoint</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
|
|||
|
<span class="kn">access_log</span> <span class="n">/var/log/nginx/cloud.rnmkcy.eu-access.log</span><span class="p">;</span>
|
|||
|
<span class="kn">error_log</span> <span class="n">/var/log/nginx/cloud.rnmkcy.eu-error.log</span><span class="p">;</span>
|
|||
|
<span class="p">}</span></code></pre></figure>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
</details>
|
|||
|
|
|||
|
<p>Vérifier et recharger nginx : <code class="language-plaintext highlighter-rouge">nginx -t && systemctl reload nginx</code></p>
|
|||
|
|
|||
|
<h3 id="nextcloud-nginx-mimes">Nextcloud Nginx mimes</h3>
|
|||
|
|
|||
|
<p><code class="language-plaintext warning highlighter-rouge">Les sections Activité et Logging dans le cadre de l’administration affiche des pages vierges</code></p>
|
|||
|
|
|||
|
<p>C’est une indication que votre serveur web n’est pas configuré pour gérer correctement les fichiers mjs.</p>
|
|||
|
|
|||
|
<p>Il faut modifier le fichier “mime.types” situé dans <code class="language-plaintext highlighter-rouge">/etc/nginx/</code>, remplaçer la ligne suivante:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>application/javascript js;
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>par</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>application/javascript js mjs;
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Puis redémarrer Nginx et php-fpm.</p>
|
|||
|
|
|||
|
<h2 id="paramétrage-nextcloud">Paramétrage Nextcloud</h2>
|
|||
|
|
|||
|
<h3 id="finaliser-installation-nextcloud">Finaliser installation Nextcloud</h3>
|
|||
|
|
|||
|
<p><code class="language-plaintext warning highlighter-rouge">Tout est paramétré avec le domaine ouestyan.fr qu'il faut remplacer par votre domaine</code></p>
|
|||
|
|
|||
|
<p>Ouvrir le lien <a href="https://cloud.rnmkcy.eu">https://cloud.rnmkcy.eu</a><br />
|
|||
|
Créer un compte administrateur et son mot de passe<br />
|
|||
|
Renseigner les éléments de la base mysql<br />
|
|||
|
<img src="/images/cloud.rnmkcy.eu02.png" alt="" width="200" /> <img src="/images/cloud.ouestyan.fr04.png" alt="" width="400" /><br />
|
|||
|
<img src="/images/cloud.rnmkcy.eu03.png" alt="" /></p>
|
|||
|
|
|||
|
<p>Se déconnecter…<br />
|
|||
|
<img src="/images/cloud.rnmkcy.eu04.png" alt="" /></p>
|
|||
|
|
|||
|
<p><strong>Modifier le fichier /var/www/nextcloud/config/config.php</strong><br />
|
|||
|
Ajouter <code class="language-plaintext highlighter-rouge">'default_phone_region' => 'FR',</code> et les lignes suivantes dans le fichier <code class="language-plaintext highlighter-rouge">/var/www/nextcloud/config/config.php</code> avant le tag de fin de fichier <code class="language-plaintext highlighter-rouge">);</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> 'default_locale' => 'fr_FR',
|
|||
|
'default_phone_region' => 'FR',
|
|||
|
'filelocking.enabled' => true,
|
|||
|
'memcache.locking' => '\OC\Memcache\Redis',
|
|||
|
'memcache.local' => '\\OC\\Memcache\\APCu',
|
|||
|
'redis' => array(
|
|||
|
'host' => 'localhost',
|
|||
|
'port' => 6379,
|
|||
|
'timeout' => 0.0,
|
|||
|
'password' => '',
|
|||
|
),
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Messagerie pour notifications</p>
|
|||
|
|
|||
|
<p>Serveur de messagerie, ajouter les lignes dans le fichier <code class="language-plaintext highlighter-rouge">/var/www/nextcloud/config/config.php</code> avant le tag de fin de fichier <code class="language-plaintext highlighter-rouge">);</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> 'mail_from_address' => 'yann',
|
|||
|
'mail_smtpmode' => 'smtp',
|
|||
|
'mail_sendmailmode' => 'smtp',
|
|||
|
'mail_domain' => 'rnmkcy.eu',
|
|||
|
'mail_smtphost' => 'rnmkcy.eu',
|
|||
|
'mail_smtpport' => '587',
|
|||
|
'mail_smtpauth' => 1,
|
|||
|
'mail_smtpname' => 'yann@rnmkcy.eu',
|
|||
|
'mail_smtppassword' => 'mot_passe_yann',
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Nextcloud Travaux cron</strong><br />
|
|||
|
Vous pouvez programmer des tâches cron de trois façons : en utilisant <strong>AJAX</strong>, <strong>Webcron</strong> ou <strong>cron</strong>.<br />
|
|||
|
La méthode recommandée est <strong>cron</strong></u>.</p>
|
|||
|
|
|||
|
<p class="info">Note : Il n’est pas obligatoire de sélectionner l’option Cron dans le menu d’administration pour les travaux en arrière-plan, car une fois que cron.php est exécuté à partir de la ligne de commande ou du service cron, il sera automatiquement réglé sur Cron.<br />
|
|||
|
<img src="/images/cloud_xoyaz_xyz06.png" alt="" width="600" /></p>
|
|||
|
|
|||
|
<p><strong>Nextcloud maintenance_window_start</strong></p>
|
|||
|
|
|||
|
<p class="warning">Le paramètre <code class="language-plaintext highlighter-rouge">maintenance_window_start</code> n’est pris en compte qu’en mode cron.</p>
|
|||
|
|
|||
|
<p>Dans le fichier config/config.php, vous pouvez spécifier cette configuration. Certaines tâches de fond ne s’exécutent qu’une fois par jour. Lorsqu’une heure est définie (le fuseau horaire est UTC) pour cette configuration, les tâches d’arrière-plan qui s’annoncent comme non sensibles au temps seront retardées pendant les heures “ouvrables” et ne s’exécuteront que dans les 4 heures suivant l’heure donnée. Ceci est par exemple utilisé pour l’expiration des activités, la formation aux connexions suspectes et les vérifications de mise à jour.</p>
|
|||
|
|
|||
|
<p class="info">Une valeur de 1, par exemple, n’exécutera ces tâches d’arrière-plan qu’entre 01h00 UTC et 05h00 UTC.</p>
|
|||
|
|
|||
|
<p>Ajouter le paramètre au fichier <code class="language-plaintext highlighter-rouge">/var/www/nextcloud/config/config.php</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> 'maintenance_window_start' => 1,
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="lldap---gestion-des-utilisateurs">LLDAP - Gestion des utilisateurs</h3>
|
|||
|
|
|||
|
<p><a href="/2024/03/05/Light_LDAP_simple_serveur_authentification.html#clients-lldap">Clients LLDAP</a></p>
|
|||
|
|
|||
|
<p>Préalable, le module php8.x-ldap doit être installé<br />
|
|||
|
Ouvrir nextcloud avec “admin”, “Applications mises en avant” et Activer LDAP puis Télécharger et activer pour que l’application apparaisse dans les “Applications actives”<br />
|
|||
|
<img src="/images/cloud.rnmkcy.eu05.png" alt="" /><br />
|
|||
|
Ensuite ouvrir “Paramètres d’administration” , “Intégration LDAP/AD”<br />
|
|||
|
<img src="/images/cloud.rnmkcy.eu06.png" alt="" /></p>
|
|||
|
|
|||
|
<ol>
|
|||
|
<li>Host: 127.0.0.1</li>
|
|||
|
<li>Port: 3890</li>
|
|||
|
<li>Utilisateur DN : uid=admin,ou=people,dc=rnmkcy,dc=eu</li>
|
|||
|
<li>Mot de passe admin LLDAP</li>
|
|||
|
<li>DN de base: dc=rnmkcy,dc=eu</li>
|
|||
|
<li>Clic Continuer</li>
|
|||
|
</ol>
|
|||
|
|
|||
|
<p>On va modifier la requête en ajoutant<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">(|(objectclass=inetOrgPerson) (memberOf=cn=nextcloud_users,ou=groups,dc=rnmkcy,dc=eu))</code><br />
|
|||
|
<img src="/images/cloud.rnmkcy.eu07.png" alt="" /> <br />
|
|||
|
Il s’affiche “9 utilisateurs trouvés”<br />
|
|||
|
La configuration LLDAP est terminée</p>
|
|||
|
|
|||
|
<p>Gestion des utilisateurs, ouvrir nextcloud avec admin , puis “Utilisateurs”<br />
|
|||
|
Créer un groupe Utilisateurs et y affecter les comptes concernés<br />
|
|||
|
<img src="/images/cloud.rnmkcy.eu11.png" alt="" /></p>
|
|||
|
|
|||
|
<p>Se déconnecter, puis se reconnecter avec le nouvel administrateur “yann” et supprimer “admin” , l’utilisateur qui a servi à l’installation de nextcloud<br />
|
|||
|
<img src="/images/cloud.rnmkcy.eu12.png" alt="" /></p>
|
|||
|
|
|||
|
<h2 id="applications-nextcloud">Applications Nextcloud</h2>
|
|||
|
|
|||
|
<h3 id="messagerie">Messagerie</h3>
|
|||
|
|
|||
|
<h4 id="mail">Mail</h4>
|
|||
|
|
|||
|
<p>Si vous avez installé un serveur mail, installer at activer l’application <strong>mail</strong> de nextcloud<br />
|
|||
|
<img src="/images/rnmkcy.eu-nexcloud20.png" alt="" /></p>
|
|||
|
|
|||
|
<h4 id="snappymail-inactif">SnappyMail (INACTIF)</h4>
|
|||
|
|
|||
|
<p><a href="/2024/01/12/SnappyMail.html#snappymail-nextcloud">SnappyMail Nextcloud</a></p>
|
|||
|
|
|||
|
<h3 id="contacts-et-calendrier">Contacts et Calendrier</h3>
|
|||
|
|
|||
|
<p>Télécharger et activer les applications <br />
|
|||
|
<img src="/images/nextcloud-calcard01.png" alt="" /></p>
|
|||
|
|
|||
|
<p>Cliquer sur l’icône “Contact” <br />
|
|||
|
<img src="/images/nextcloud-calcard02.png" alt="" width="600" /><br />
|
|||
|
<img src="/images/nextcloud-calcard03.png" alt="" width="600" /><br />
|
|||
|
<img src="/images/nextcloud-calcard04.png" alt="" width="600" /><br />
|
|||
|
Pour le lien<br />
|
|||
|
<img src="/images/nextcloud-calcard04a.png" alt="" width="600" /><br />
|
|||
|
Lien interne utilisateur : <a href="https://cloud.rnmkcy.eu/remote.php/dav/addressbooks/users/dentifiant_hexa_utilisateur/contacts/">https://cloud.rnmkcy.eu/remote.php/dav/addressbooks/users/dentifiant_hexa_utilisateur/contacts/</a></p>
|
|||
|
|
|||
|
<p>Cliquer sur l’icône “Agenda” <br />
|
|||
|
<img src="/images/nextcloud-calcard05.png" alt="" width="600" /><br />
|
|||
|
<img src="/images/nextcloud-calcard06.png" alt="" width="600" /><br />
|
|||
|
<img src="/images/nextcloud-calcard07.png" alt="" width="600" /></p>
|
|||
|
|
|||
|
<p>Pour les partages<br />
|
|||
|
<img src="/images/nextcloud-calcard08.png" alt="" width="200" /><br />
|
|||
|
Adresse caldav principal : <a href="https://cloud.rnmkcy.eu/remote.php/dav">https://cloud.rnmkcy.eu/remote.php/dav</a></p>
|
|||
|
|
|||
|
<p>Pour les clients android, thunderbird<br />
|
|||
|
Cliquer sur le lien “Modifier et partager l’agenda” de l’utilisateur yann <br />
|
|||
|
<img src="/images/nextcloud-calcard09.png" alt="" width="400" /><br />
|
|||
|
Lien interne utilisateur : <a href="https://cloud.rnmkcy.eu/remote.php/dav/calendars/Identifiant_hexa_utilisateur/personal/">https://cloud.rnmkcy.eu/remote.php/dav/calendars/Identifiant_hexa_utilisateur/personal/</a></p>
|
|||
|
|
|||
|
<h3 id="login-mot-de-passe-application">Login mot de passe application</h3>
|
|||
|
|
|||
|
<p>Les applications clientes de nextcloud ne peuvent pas se connecter sur nextcloud avec une authentification à 2 facteurs, il faut créer un accès login + mot de passe<br />
|
|||
|
Se connecter à Nextcloud puis : Personnel → Sécurité → Appareils & sessions<br />
|
|||
|
<img src="/images/nextcloud-mpappli01.png" alt="" /> <br />
|
|||
|
Sauvegarder les 2 paramètres (utilisateur et mot de passe) pour une utilisation sur les applications clientes…</p>
|
|||
|
|
|||
|
<h3 id="nextcloud-music">Nextcloud Music</h3>
|
|||
|
|
|||
|
<p>« Music » est une application pour OwnCloud et Nextcloud qui joue à la fois le rôle de serveur de musique et celui de client Web.</p>
|
|||
|
|
|||
|
<p>Les principales fonctionnalités de Nextcloud Music sont :</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>l’indexation de la musique présente sur le stockage Nextcloud,</li>
|
|||
|
<li>la navigation dans sa bibliothèque et l’écoute de sa musique via une interface Web intégrée à Nextcloud,</li>
|
|||
|
<li>et la fourniture d’APIs permettant à des applications tierces de s’y connecter.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>« Smart playlist » est une sélection (aléatoire ?) de 100 titres que vous pouvez écouter en un clic. Contrairement aux autres playlists, la « Smart playlist » n’est pas accessible en dehors de l’interface Web, mais il est possible de l’enregistrer vers une playlist régulière qui sera alors accessible aux applications tierces.</p>
|
|||
|
|
|||
|
<p>« Internet radio » et permet d’ajouter et d’écouter des Web radio. Elle fonctionne bien, mais il est important de noter que si votre instance Nextcloud est accessible en HTTPS [elle devrait !], le flux de la radio devra impérativement utiliser ce protocole également. Il s’agit-là d’une limitation liée au navigateur, qui pour des raisons de sécurité empêche d’accéder à des ressources HTTP depuis une page servie en HTTPS.</p>
|
|||
|
|
|||
|
<p>Et la dernière fonctionnalité permet de s’abonner à des Podcast via des flux RSS.</p>
|
|||
|
|
|||
|
<p>Activer l’application <strong>Music</strong><br />
|
|||
|
<img src="/images/nextcloud-music01.png" alt="" /></p>
|
|||
|
|
|||
|
<p>Ouvrir l’application “Music” et cliquer sur Settings<br />
|
|||
|
<img src="/images/nextcloud-music02.png" alt="" /></p>
|
|||
|
|
|||
|
<p>Pour les applications android, un accès avec mot de passe<br />
|
|||
|
<img src="/images/nextcloud-music03.png" alt="" /></p>
|
|||
|
|
|||
|
<p>Android <strong>Power Ampache 2</strong> (<a href="https://github.com/icefields/Power-Ampache-2">https://github.com/icefields/Power-Ampache-2</a>)<br />
|
|||
|
<em>Power Ampache 2 est un client musical riche en fonctionnalités conçu pour Ampache, Nextcloud Music et les backends compatibles. Il offre toutes les fonctionnalités des autres lecteurs de musique grand public, tels que Spotify, YouTube Music et Apple Music, et bien plus encore. Avec Power Ampache 2, profitez « réellement » du téléchargement et de l’exportation de fichiers musicaux, de l’accès aux paroles, de la prise en charge de plusieurs comptes et d’une expérience sans publicité et sans suivi.</em></p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>Listes de lecture générées uniques (smartlists)</li>
|
|||
|
<li>“Spin it!” bouton pour générer une liste de lecture pour vous.</li>
|
|||
|
<li>Mode sombre et clair avec couleurs d’interface adaptatives, ou choisissez/créez votre propre thème.</li>
|
|||
|
<li>Prise en charge des touches multimédias</li>
|
|||
|
<li>Chaque fonctionnalité Bluetooth est disponible dans l’application.</li>
|
|||
|
<li>Notifications de chansons avec commandes de lecture. Également sur l’écran de verrouillage.</li>
|
|||
|
<li>Collections d’albums, d’artistes et de chansons</li>
|
|||
|
<li>Recherche avancée</li>
|
|||
|
<li>Mode hors ligne puissant</li>
|
|||
|
<li>Créez, modifiez et partagez vos listes de lecture</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p><a href="https://f-droid.org/repo/luci.sixsixsix.powerampache2.fdroid_61.apk">Télécharger APK</a>, <a href="https://f-droid.org/repo/luci.sixsixsix.powerampache2.fdroid_61.apk.asc">Signature PGP</a></p>
|
|||
|
|
|||
|
<h3 id="office">Office</h3>
|
|||
|
|
|||
|
<h4 id="onlyoffice-inactif">OnlyOffice (INACTIF)</h4>
|
|||
|
|
|||
|
<p><a href="/2023/08/19/OnlyOffice_pour_YunoHost.html">OnlyOffice YunoHost, Nextcloud et Archlinux</a></p>
|
|||
|
|
|||
|
<h4 id="collabora-online-inactif">Collabora Online (INACTIF)</h4>
|
|||
|
|
|||
|
<p><a href="/2024/05/18/Collabora_Debian.html">Collabora</a></p>
|
|||
|
|
|||
|
<h3 id="nextcloud-webdav">Nextcloud WebDAV</h3>
|
|||
|
|
|||
|
<p><em>Dans le domaine des réseaux informatiques, davfs2 est un outil Linux permettant de se connecter à des partages WebDAV comme s’il s’agissait de disques locaux. Il s’agit d’un système de fichiers open-source sous licence GPL pour le montage de serveurs WebDAV. Il utilise l’API du système de fichiers FUSE pour communiquer avec le noyau et la bibliothèque neon WebDAV pour communiquer avec le serveur web.</em></p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li><a href="https://docs.nextcloud.com/server/latest/user_manual/fr/files/access_webdav.html">Accès aux fichiers Nextcloud avec WebDAV</a></li>
|
|||
|
<li><a href="https://sleeplessbeastie.eu/2017/09/25/how-to-mount-webdav-share-using-systemd/">How to mount WebDAV share using systemd</a></li>
|
|||
|
<li><a href="https://sleeplessbeastie.eu/2017/09/04/how-to-mount-webdav-share/">How to mount WebDAV share</a></li>
|
|||
|
<li><a href="https://wiki.archlinux.org/title/Davfs2">davfs2 archwiki</a></li>
|
|||
|
<li><a href="https://www.hagemann.ws/blog/linux-mount-webdav-share-using-fstab-and-davfs2.html">Linux: Mount WebDav-Share using fstab and davfs2</a></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h3 id="nextcloud-notes">Nextcloud Notes</h3>
|
|||
|
|
|||
|
<p><strong>Notes</strong><br />
|
|||
|
L’application Notes est une application de prise de notes pour Nextcloud. Elle fournit des catégories pour une meilleure organisation et supporte le formatage en utilisant la syntaxe Markdown. Les notes sont sauvegardées comme des fichiers dans votre Nextcloud, vous pouvez donc les voir et les éditer avec n’importe quel client Nextcloud. De plus, une API REST séparée permet une intégration facile dans des applications tierces (actuellement, il existe des applications de notes pour Android, iOS et la console qui permettent un accès pratique à vos notes Nextcloud). D’autres fonctionnalités permettent de marquer des notes comme favorites.</p>
|
|||
|
|
|||
|
<p><strong>QOwnNotesAPI</strong></p>
|
|||
|
|
|||
|
<p><em>QOwnNotesAPI est l’API Nextcloud/ownCloud pour QOwnNotes, le bloc-notes open source pour Linux, macOS et Windows, qui fonctionne avec l’application de notes de Nextcloud/ownCloud.</em></p>
|
|||
|
|
|||
|
<p>Le seul but de cette application est de fournir un accès API à votre serveur Nextcloud/ownCloud pour votre installation de bureau QOwnNotes, vous ne pouvez pas utiliser cette application pour autre chose, si vous n’avez pas QOwnNotes installé sur votre ordinateur de bureau !</p>
|
|||
|
|
|||
|
<p>Archlinux QOwnNotes</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yay -S qownnotes
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="mise-à-jour-nextcloud">Mise à jour Nextcloud</h2>
|
|||
|
|
|||
|
<p><img src="/images/nextcloud-maj01.png" alt="" width="500" /></p>
|
|||
|
|
|||
|
<h3 id="interface">Interface</h3>
|
|||
|
|
|||
|
<p>Cliquer sur <strong>Ouvrir l’interface de mise à jour</strong><br />
|
|||
|
<img src="/images/nextcloud-maj02.png" alt="" width="300" /><br />
|
|||
|
<img src="/images/nextcloud-maj03.png" alt="" width="300" /><br />
|
|||
|
<img src="/images/nextcloud-maj04.png" alt="" width="300" /><br />
|
|||
|
Retour sur la page d’accueil à la fin de la mise à jour</p>
|
|||
|
|
|||
|
<h3 id="manuellement">Manuellement</h3>
|
|||
|
|
|||
|
<p class="warning">Si vous effectuez une mise à niveau à partir d’une version majeure précédente, veuillez d’abord consulter les <a href="https://docs.nextcloud.com/server/latest/admin_manual/release_notes/index.html#critical-changes">modifications critiques (en)</a></p>
|
|||
|
|
|||
|
<p>Commencez toujours par effectuer une nouvelle sauvegarde et en désactivant toutes les applications tierces.</p>
|
|||
|
|
|||
|
<p>1 - Sauvegardez vos fichiers Nextcloud Server existants ,votre base de données, votre répertoire de données et <code class="language-plaintext highlighter-rouge">config.php</code>. (Voir <a href="https://docs.nextcloud.com/server/latest/admin_manual/maintenance/backup.html">Backup</a> , pour les informations de restauration, voir<a href="https://docs.nextcloud.com/server/latest/admin_manual/maintenance/restore.html"> Restoring backup</a> )</p>
|
|||
|
|
|||
|
<p>2 - Téléchargez et décompressez la dernière version de Nextcloud Server (fichier d’archive) depuis <a href="https://download.nextcloud.com/server/releases/">https://download.nextcloud.com/server/releases/</a> dans un répertoire vide en dehors de votre installation actuelle.<br />
|
|||
|
Pour décompresser votre nouvelle archive tar, exécutez : <code class="language-plaintext highlighter-rouge">unzip nextcloud-[version].zip</code> ou <code class="language-plaintext highlighter-rouge">tar -xjf nextcloud-[version].tar.bz2</code></p>
|
|||
|
|
|||
|
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir</span> <span class="nt">-p</span> ~/temp
|
|||
|
<span class="nb">cd</span> ~/temp
|
|||
|
wget https://download.nextcloud.com/server/releases/latest-28.tar.bz2
|
|||
|
<span class="nb">tar</span> <span class="nt">-xjf</span> latest-28.tar.bz2
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>3 - Arrêtez votre serveur Web.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl stop nginx
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>4 - Si vous exécutez une tâche cron pour la gestion interne de nextcloud, désactivez-la en commentant l’entrée dans le fichier crontab.(Le proriétaire du dossier est www-data ou nextcloud (<code class="language-plaintext highlighter-rouge">ls -la /var/www</code>)</p>
|
|||
|
|
|||
|
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#sudo crontab -u www-data -e</span>
|
|||
|
<span class="nb">sudo </span>crontab <span class="nt">-u</span> nextcloud <span class="nt">-e</span>
|
|||
|
<span class="c"># commenter</span>
|
|||
|
<span class="c">#*/5 * * * * php -f /var/www/nextcloud/cron.php</span>
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>(Mettez un # au début de la ligne correspondante.)</p>
|
|||
|
|
|||
|
<p>5 - Renommez votre répertoire Nextcloud actuel, par exemple nextcloud-old.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo mv /var/www/nextcloud /var/www/nextcloud-old
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>6 - La décompression de la nouvelle archive crée un nouveau répertoire nextcloud rempli avec vos nouveaux fichiers serveur. Déplacez ce répertoire et son contenu vers l’emplacement d’origine de votre ancien serveur. Par exemple <code class="language-plaintext highlighter-rouge">/var/www/</code>, pour qu’une fois de plus vous ayez <code class="language-plaintext highlighter-rouge">/var/www/nextcloud</code></p>
|
|||
|
|
|||
|
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo mv</span> ~/temp/nextcloud /var/www/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>7 - Copiez le config/config.phpfichier de votre ancien répertoire Nextcloud vers votre nouveau répertoire Nextcloud.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo cp /var/www/nextcloud-old/config/config.php /var/www/nextcloud/config/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>8 - Si vous conservez votre data/répertoire dans votre nextcloud/répertoire, copiez-le de votre ancienne version de Nextcloud vers votre nouveau nextcloud/. Si vous le conservez à l’extérieur nextcloud/, vous n’avez rien à faire avec, car son emplacement est configuré dans votre fichier d’origine config.phpet aucune des étapes de mise à niveau ne le touche.</p>
|
|||
|
|
|||
|
<p>9 - Si vous utilisez une application tierce, il se peut qu’elle ne soit pas toujours disponible dans votre instance Nextcloud mise à niveau/nouvelle. Pour vérifier cela, comparez une liste des applications du nouveau nextcloud/apps/dossier à une liste des applications de votre dossier sauvegardé/ancien nextcloud/apps/. Si vous trouvez des applications tierces dans l’ancien dossier qui doivent se trouver dans l’instance nouvelle/mise à niveau, copiez-les simplement et assurez-vous que les autorisations sont configurées comme indiqué ci-dessous.</p>
|
|||
|
|
|||
|
<p>10 - Si vous avez des dossiers d’applications supplémentaires comme par exemple nextcloud/apps-extras ou nextcloud/apps-external, assurez-vous de les transférer/conserver également dans le dossier mis à niveau.</p>
|
|||
|
|
|||
|
<p>11 - Si vous utilisez un thème tiers, assurez-vous de le copier de votre themes/répertoire vers votre nouveau. Il est possible que vous deviez y apporter quelques modifications après la mise à niveau.</p>
|
|||
|
|
|||
|
<p>12 - Ajustez la propriété et les autorisations des fichiers :</p>
|
|||
|
|
|||
|
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># en mode su</span>
|
|||
|
<span class="nb">sudo</span> <span class="nt">-s</span>
|
|||
|
<span class="c"># si propriétaire www-data</span>
|
|||
|
<span class="nb">chown </span>www-data:www-data <span class="nt">-R</span> /var/www/nextcloud
|
|||
|
<span class="c"># si propriétaire nextcloud</span>
|
|||
|
<span class="nb">chown </span>nextcloud:www-data <span class="nt">-R</span> /var/www/nextcloud
|
|||
|
find /var/www/nextcloud/ <span class="nt">-type</span> d <span class="nt">-exec</span> <span class="nb">chmod </span>750 <span class="o">{}</span> <span class="se">\;</span>
|
|||
|
find /var/www/nextcloud/ <span class="nt">-type</span> f <span class="nt">-exec</span> <span class="nb">chmod </span>640 <span class="o">{}</span> <span class="se">\;</span>
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>13 - Redémarrez votre serveur Web.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl start nginx
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>14 - Lancez maintenant la mise à niveau depuis la ligne de commande en utilisant occ</p>
|
|||
|
|
|||
|
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo</span> <span class="nt">-s</span>
|
|||
|
<span class="nb">cd</span> /var/www/nextcloud
|
|||
|
<span class="c"># si propriétaire www-data</span>
|
|||
|
<span class="nb">sudo</span> <span class="nt">-u</span> www-data php occ upgrade
|
|||
|
<span class="c"># si propriétaire nextcloud</span>
|
|||
|
<span class="nb">sudo</span> <span class="nt">-u</span> nextcloud php occ upgrade
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>(!) cela DOIT être exécuté à partir de votre répertoire d’installation nextcloud</p>
|
|||
|
|
|||
|
<p>15 - L’opération de mise à niveau prend de quelques minutes à quelques heures, selon la taille de votre installation. Une fois l’opération terminée, vous verrez un message de réussite ou un message d’erreur qui vous indiquera où l’erreur s’est produite.</p>
|
|||
|
|
|||
|
<p>16 - Réactivez la tâche cron nextcloud. (Voir l’étape 4 ci-dessus.)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># si propriétaire www-data
|
|||
|
sudo crontab -u www-data -e
|
|||
|
# si propriétaire nextcloud
|
|||
|
sudo crontab -u nextcloud -e
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>(Supprimez le # au début de la ligne correspondante dans le fichier crontab.)</p>
|
|||
|
|
|||
|
<p><strong>Connectez-vous</strong></p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>jetez un œil au bas de votre page d’administration pour vérifier le numéro de version.</li>
|
|||
|
<li>Vérifiez vos autres paramètres pour vous assurer qu’ils sont corrects.</li>
|
|||
|
<li>Accédez à la page Applications et examinez les applications principales pour vous assurer que les bonnes sont activées.</li>
|
|||
|
<li>Réactivez vos applications tierces.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h2 id="partage">Partage</h2>
|
|||
|
|
|||
|
<h3 id="fédération-nextcloud">Fédération Nextcloud</h3>
|
|||
|
|
|||
|
<p>Un service est dit fédéré si deux usagers de ce service peuvent interagir sans utiliser le même prestataire de service.</p>
|
|||
|
|
|||
|
<p>Entre deux comptes sur des Nextcloud différents</p>
|
|||
|
|
|||
|
<p><em>carla (compte cloud.xoyize.xyz) souhaite partager le dossier Camera avec yann (compte cloud.rnmkcy.eu)</em></p>
|
|||
|
|
|||
|
<p><u>yann (compte cloud.rnmkcy.eu)</u></p>
|
|||
|
|
|||
|
<p>Il faut récupérer l’ID de fédération<br />
|
|||
|
<img src="/images/nextcloud-federation05.png" alt="" /><br />
|
|||
|
Du type <a href="mailto:5bcd25ef-356abc-a5@cloud.rnmkcy.eu">5bcd25ef-356abc-a5@cloud.rnmkcy.eu</a></p>
|
|||
|
|
|||
|
<p><u>carla (compte cloud.xoyize.xyz)</u></p>
|
|||
|
|
|||
|
<ol>
|
|||
|
<li>Il faut cliquer sur le symbole de partage en bout de ligne du dossier <strong>Camera</strong><br />
|
|||
|
<img src="/images/nextcloud-federation00.png" alt="" /></li>
|
|||
|
<li>Puis saisir l’identifiant fédération Nextcloud de yann (compte cloud.rnmkcy.eu) <a href="mailto:5bcd25ef-356abc-a5@cloud.rnmkcy.eu">5bcd25ef-356abc-a5@cloud.rnmkcy.eu</a><br />
|
|||
|
<img src="/images/nextcloud-federation01.png" alt="" /></li>
|
|||
|
<li><strong>Autoriser la modification</strong> et <strong>Enregistrer</strong> <br />
|
|||
|
<img src="/images/nextcloud-federation02.png" alt="" /></li>
|
|||
|
</ol>
|
|||
|
|
|||
|
<p>Le partage est établi avec yann<br />
|
|||
|
<img src="/images/nextcloud-federation03.png" alt="" /><br />
|
|||
|
<img src="/images/nextcloud-federation04.png" alt="" /></p>
|
|||
|
|
|||
|
<p>Vérification sur <u>yann (compte cloud.rnmkcy.eu)</u><br />
|
|||
|
Il faut aller dans les notifications et accepter le partage<br />
|
|||
|
<img src="/images/nextcloud-federation06.png" alt="" /><br />
|
|||
|
<img src="/images/nextcloud-federation07.png" alt="" /></p>
|
|||
|
|
|||
|
<h3 id="synchroniser-deux-serveurs-nextcloud">Synchroniser deux serveurs Nextcloud</h3>
|
|||
|
|
|||
|
<p>depuis deux sites différents</p>
|
|||
|
|
|||
|
<p>La synchronisation de deux serveurs multiples Nextcloud à partir de deux sites différents implique la mise en place d’une fédération de serveur à serveur, qui permet aux deux instances de partager des fichiers, des dossiers et d’autres données. Voici un guide étape par étape sur la façon d’y parvenir :</p>
|
|||
|
|
|||
|
<p>Conditions requises :</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>Deux instances Nextcloud, chacune installée sur un site différent.</li>
|
|||
|
<li>URLs accessibles au public pour les deux instances.</li>
|
|||
|
<li>Connectivité réseau entre les deux sites (accès internet ou connexion directe).</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Etapes pour synchroniser deux serveurs Nextcloud :</p>
|
|||
|
|
|||
|
<p>Activer l’application Federation : Sur les deux instances Nextcloud, s’assurer que l’application “Federation” est activée. Cette application permet aux serveurs de communiquer et de partager des données.</p>
|
|||
|
|
|||
|
<p>Configurer le serveur de confiance sur la première instance Nextcloud (Site A) :</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>Se connecter en tant qu’administrateur.</li>
|
|||
|
<li>Aller dans “Paramètres d’administration” > “Administration” > “Partage”.</li>
|
|||
|
<li>Descendez jusqu’à la section “Serveurs de confiance” et cliquez sur “Ajouter un serveur de confiance”.</li>
|
|||
|
<li>Entrez l’URL de la deuxième instance Nextcloud (Site B) et générez un jeton.<br />
|
|||
|
<img src="/images/nextcloud-federation08.png" alt="" /></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Configurer le serveur de confiance sur la deuxième instance (Site B)</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>Se connecter en tant qu’administrateur.</li>
|
|||
|
<li>Aller dans “Paramètres d’administration” > “Administration” > “Partage”.</li>
|
|||
|
<li>Descendez jusqu’à la section “Serveurs de confiance” et cliquez sur “Ajouter un serveur de confiance”.</li>
|
|||
|
<li>Entrez l’URL de la première instance Nextcloud (Site A)</li>
|
|||
|
<li><img src="/images/nextcloud-federation09.png" alt="" /></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Lancez le partage<br />
|
|||
|
Sur l’une des instances (disons le site A) :</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>Connectez-vous en tant qu’utilisateur.</li>
|
|||
|
<li>Naviguez jusqu’au fichier ou dossier que vous souhaitez partager avec l’autre instance (Site B).</li>
|
|||
|
<li>Cliquez sur le bouton “Partager” et entrez l’adresse e-mail d’un utilisateur sur la deuxième instance (Site</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Choisissez les permissions appropriées (lecture seule, lecture/écriture, etc.).</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>Cliquez sur “Partager”.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Accepter l’invitation au partage :<br />
|
|||
|
Sur l’autre instance (Site B) :</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>Connectez-vous en tant qu’utilisateur ayant reçu l’invitation de partage.</li>
|
|||
|
<li>Vous devriez voir une notification ou une invitation de partage entrante. Acceptez le partage.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Synchronisation des données :<br />
|
|||
|
Une fois le partage accepté, les données seront synchronisées entre les deux instances. Les modifications effectuées sur une instance seront répercutées sur l’autre. Notez que la synchronisation peut prendre un certain temps en fonction de la taille des données et de la bande passante disponible sur le réseau.</p>
|
|||
|
|
|||
|
<p>Surveiller et gérer :<br />
|
|||
|
Vous pouvez surveiller l’état des connexions de serveur à serveur et des fichiers partagés par le biais de l’interface Nextcloud. Toute mise à jour ou modification sera propagée entre les deux instances.</p>
|
|||
|
|
|||
|
<p>Répéter pour d’autres partages :<br />
|
|||
|
Vous pouvez répéter le processus pour partager d’autres fichiers et dossiers entre les deux instances.</p>
|
|||
|
|
|||
|
<p>Rappelez-vous que cette configuration nécessite que les deux instances disposent d’une connectivité internet fiable ou d’une connexion réseau dédiée entre les sites. Veillez également à ce que les deux instances soient à jour et correctement sécurisées afin de préserver l’intégrité et la confidentialité des données partagées.</p>
|
|||
|
|
|||
|
<h2 id="nextcloud-authentification">Nextcloud Authentification</h2>
|
|||
|
|
|||
|
<h3 id="mot-de-passe-dapplication">Mot de passe d’application</h3>
|
|||
|
|
|||
|
<p><em>créer un mot de passe d’application afin de permettre à des applications de se connecter rapidement et de façon sécurisée à votre compte Nextcloud</em></p>
|
|||
|
|
|||
|
<p><img src="/images/mp-appli01.png" alt="" /><br />
|
|||
|
<img src="/images/mp-appli02.png" alt="" /></p>
|
|||
|
|
|||
|
<p>En cas de problème, vous pouvez notamment en cliquant sur les trois points à côté de votre mot de passe d’application<br />
|
|||
|
<img src="/images/mp-appli03.png" alt="" /></p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li><strong>Effacer l’appareil</strong> commande l’effacement à distance , ce qui ordonne à l’appareil (s’il a été volé par exemple) d’effacer tous les fichiers de votre compte Nextcloud qu’il contient.</li>
|
|||
|
<li><strong>Révoquer</strong> le mot de passe, ce qui le désactive et empêche toute connexion ultérieure par ce mot de passe à votre compte Nextcloud, sans aucun impact sur votre mot de passe principal Nextcloud, qui reste sûr.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h3 id="connexion-mobile-android-à-un-compte-nextcloud">Connexion mobile Android à un compte Nextcloud</h3>
|
|||
|
|
|||
|
<p>Créer un mot de passe application, voir ci-dessus. Le mot de passe d’application se nomme “Mobiles”</p>
|
|||
|
|
|||
|
<p>Sur votre mobile, installez l’application Nextcloud, disponible sur le <a href="https://play.google.com/store/apps/details?id=com.nextcloud.client&gl=US">Play Store</a> ou sur <a href="https://f-droid.org/en/packages/com.nextcloud.client/">F-Droid</a>.<br />
|
|||
|
Lancez l’application et cliquez sur Se connecter.<br />
|
|||
|
<img src="/images/mp-appli04.png" alt="" height="400" /></p>
|
|||
|
|
|||
|
<p>L’application lance un navigateur, cliquez sur <strong>Authentification alternative en utilisant un mot de passe d’application.</strong><br />
|
|||
|
<img src="/images/mp-appli05.png" alt="" height="400" /> <img src="/images/mp-appli06.png" alt="" height="400" /><br />
|
|||
|
Connexion établie<br />
|
|||
|
<img src="/images/mp-appli07.png" alt="" height="400" /></p>
|
|||
|
|
|||
|
<h3 id="double-facteur---totp">Double facteur - TOTP</h3>
|
|||
|
|
|||
|
<p>Paramètres → Applications → Applications mises en avant <br />
|
|||
|
<img src="/images/nextcloud_hub07.png" alt="" /><br />
|
|||
|
Activer “Two-Factor TOTP Provider”</p>
|
|||
|
|
|||
|
<p>Paramètres → Administration settings → Sécurité dans la rubrique Administration <br />
|
|||
|
<img src="/images/cloud.ouestyan.fr10a.png" alt="" /> <br />
|
|||
|
Puis cliquer sur <strong>Enregistrer les modifications</strong></p>
|
|||
|
|
|||
|
<p>Aller ensuite sur Paramètres personnels → Sécurité dans la rubrique Personnel
|
|||
|
<img src="/images/cloud.ouestyan.fr10b.png" alt="" /></p>
|
|||
|
|
|||
|
<p>Après avoir activé authentification TOTP (saisie du mot de passe)<br />
|
|||
|
<img src="/images/cloud.ouestyan.fr11.png" alt="" /> <br />
|
|||
|
Enter le <strong>secret TOTP</strong> dans le ou les applications TOPT <br />
|
|||
|
Saisir le code de vérification générer par votre application et cliquer sur “Vérifier” <br />
|
|||
|
Ensuite cliquer sur “Générer des codes de récupération”<br />
|
|||
|
<img src="/images/cloud.ouestyan.fr11a.png" alt="" /></p>
|
|||
|
|
|||
|
<h3 id="double-facteur---clé-de-sécurité">Double facteur - Clé de sécurité</h3>
|
|||
|
|
|||
|
<p><em><img src="/images/yubikey5nfc.png" alt="" height="50" />YubiKey 5 Series Une gamme multiprotocole (FIDO2/WebAuthn, U2F, Smart Card, OpenPGP, OTP) qui est le premier choix des entreprises et qui prend en charge la fonction sans mot de passe</em></p>
|
|||
|
|
|||
|
<ol>
|
|||
|
<li>La clé “Yubikey 5 NFC” est connectée sur un port USB de l’ordinateur</li>
|
|||
|
<li>Nextcloud, Paramétrage “Personnel” -> “Sécurité” -> “Authentification à deux facteurs” cliquer sur “Ajouter une clé de sécurité”</li>
|
|||
|
<li>Valider la prise en charge <img src="/images/yubikey-validation.png" alt="" /></li>
|
|||
|
<li>Donner un nom :<br />
|
|||
|
<img src="/images/nextcloud_hub06a1.png" alt="" /><br />
|
|||
|
Faire la même opération avec les autres clés<br />
|
|||
|
Se déconnecter de nextcloud</li>
|
|||
|
</ol>
|
|||
|
|
|||
|
<h3 id="sans-mot-de-passe---webauthnn">Sans mot de passe - WebAuthnn</h3>
|
|||
|
|
|||
|
<p><em><img src="/images/yubikey5nfc.png" alt="" height="50" />YubiKey 5 Series Une gamme multiprotocole (FIDO2/WebAuthn, U2F, Smart Card, OpenPGP, OTP) qui est le premier choix des entreprises et qui prend en charge la fonction sans mot de passe</em></p>
|
|||
|
|
|||
|
<p><code class="language-plaintext warning highlighter-rouge">ATTENTION: Fonctionne uniquement sur les navigateurs Chrome, Firefox et Edge</code></p>
|
|||
|
|
|||
|
<p>Paramètres → Applications → Applications mises en avant <br />
|
|||
|
<img src="/images/nextcloud_hub08.png" alt="" /><br />
|
|||
|
Télécharger et activer l’application <strong>Two-Factor WebAuthnn</strong></p>
|
|||
|
|
|||
|
<ol>
|
|||
|
<li>La clé “Yubikey 5 NFC” est connectée sur un port USB de l’ordinateur</li>
|
|||
|
<li>Nextcloud, Paramétrage “Personnel” -> “Sécurité” -> “Authentification sans mot de passe” cliquer sur “Ajouter un périphérique WebAuthnn”<br />
|
|||
|
<img src="/images/nextcloud_hub10.png" alt="" /></li>
|
|||
|
<li>Valider la prise en charge <img src="/images/yubikey-validation.png" alt="" /></li>
|
|||
|
<li>Donner un nom :<br />
|
|||
|
<img src="/images/nextcloud_hub06a.png" alt="" /><br />
|
|||
|
Faire la même opération avec les autres clés<br />
|
|||
|
Se déconnecter de nextcloud</li>
|
|||
|
</ol>
|
|||
|
|
|||
|
<p><strong>Utilisation connexion sans mot de passe</strong><br />
|
|||
|
Ouvrir Nextcloud<br />
|
|||
|
<img src="/images/nextcloud_webauthnn01.png" alt="" /></p>
|
|||
|
|
|||
|
<p><img src="/images/nextcloud_webauthnn03a.png" alt="" /><br />
|
|||
|
Saisir le nom utilisateur puis cliquer sur Se connecter<br />
|
|||
|
<img src="/images/nextcloud_webauthnn03a1.png" alt="" /><br />
|
|||
|
Ensuite vous aurez le message suivant, cliquer sur “Clé de sécurité”<br />
|
|||
|
<img src="/images/nextcloud_webauthnn03.png" alt="" /></p>
|
|||
|
|
|||
|
<p><img src="/images/nextcloud_webauthnn03c.png" alt="" /></p>
|
|||
|
|
|||
|
<h4 id="firefox-linux-desktop">Firefox linux desktop</h4>
|
|||
|
|
|||
|
<p>ouvrir le lien https du cloud<br />
|
|||
|
<img src="/images/nextcloud_hub06b.png" alt="" /> <img src="/images/nextcloud_hub06c.png" alt="" /><br />
|
|||
|
<img src="/images/nextcloud_hub06d.png" alt="" /> -> <img src="/images/yubikey-validation.png" alt="" /></p>
|
|||
|
|
|||
|
<p><img src="/images/nextcloud_hub06e.png" alt="" /></p>
|
|||
|
|
|||
|
<h4 id="firefox-android-mobile">Firefox android mobile</h4>
|
|||
|
|
|||
|
<p><em>Le fonctionnement de la clé NFC est utilisé</em></p>
|
|||
|
|
|||
|
<h2 id="nextcloud-sauvegarde-restauration">Nextcloud Sauvegarde Restauration</h2>
|
|||
|
|
|||
|
<h3 id="accès-boîte-de-stockage">Accès boîte de stockage</h3>
|
|||
|
|
|||
|
<p>Créer un accès à la boîte de stockage <code class="language-plaintext highlighter-rouge">u326239@u326239.your-storagebox.de</code> via sftp et un jeu de clé ed25519</p>
|
|||
|
|
|||
|
<p>Générer une paire de clé curve25519-sha256 (ECDH avec Curve25519 et SHA2)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh-keygen -t ed25519 -o -a 100 -f ~/.ssh/bx11-xoyize.net
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ajouter la clé publique <code class="language-plaintext highlighter-rouge">bx11-xoyize.net.pub</code> au fichier <code class="language-plaintext highlighter-rouge">.ssh/authorized_keys</code> de la boîte de stockage</p>
|
|||
|
|
|||
|
<p>Tester la connexion, créer dossier xoyize.net et sortir</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sftp -P 23 -i ~/.ssh/bx11-xoyize.net u326239@u326239.your-storagebox.de
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Première connexion</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>The authenticity of host '[u326239.your-storagebox.de]:23 ([2a01:4f8:261:59d3::2]:23)' can't be established.
|
|||
|
ED25519 key fingerprint is SHA256:XqONwb1S0zuj5A1CDxpOSuD2hnAArV1A3wKY7Z3sdgM.
|
|||
|
This key is not known by any other names.
|
|||
|
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
|
|||
|
Warning: Permanently added '[u326239.your-storagebox.de]:23' (ED25519) to the list of known hosts.
|
|||
|
Connected to u326239.your-storagebox.de.
|
|||
|
sftp> mkdir backup/xoyize.net
|
|||
|
sftp> exit
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="sauvegarde-nextcloud">Sauvegarde nextcloud</h3>
|
|||
|
|
|||
|
<p>En mode su dans le dossier /var/www/nextcloud</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
|
|||
|
cd /var/www/nextcloud
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><a href="https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/occ_command.html#">Using the occ command</a></p>
|
|||
|
|
|||
|
<p>Pour sauvegarder une installation Nextcloud, quatre choses principales</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>Le dossier de configuration</li>
|
|||
|
<li>Le dossier de données <strong>/srv/nextcloud-data/</strong></li>
|
|||
|
<li>Le dossier thématique</li>
|
|||
|
<li>La base de données</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p class="warning">ATTENTION : Utilisateur <strong>nextcloud</strong> au lieu de <strong>www-data</strong> pour les dossiers</p>
|
|||
|
|
|||
|
<p>Créer un dossier pour stocker le mot de passe de la base de données</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir -p /home/yani/.local/share/nextcloud
|
|||
|
echo "mot_passe_mysql_nextcloud" > /home/yani/.local/share/nextcloud/dbpassword
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Mode maintenance</strong><br />
|
|||
|
Le mode maintenance verrouille les sessions des utilisateurs connectés et empêche les nouvelles connexions afin d’éviter les incohérences de vos données. Vous devez exécuter occ comme utilisateur HTTP ou nextcloud</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -u nextcloud php occ maintenance:mode --on
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Renvoie <strong>Maintenance mode enabled</strong></p>
|
|||
|
|
|||
|
<p><strong>Sauvegarde dossiers</strong><br />
|
|||
|
Il suffit de copier vos dossiers de configuration, de données et de thème (ou même votre dossier d’installation et de données de Nextcloud) vers un endroit à l’extérieur de votre environnement Nextcloud</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># dossier /var/www/nextcloud
|
|||
|
rsync -Aavx --delete --rsync-path='rsync' -e 'ssh -p 23 -i /home/yani/.ssh/bx11-xoyize.net -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' /var/www/nextcloud u326239@u326239.your-storagebox.de:backup/xoyize.net/nextcloud-dirbkp_`date +"%Y%m%d"`/
|
|||
|
|
|||
|
# nextcloud data
|
|||
|
rsync -Aavx --delete --rsync-path='rsync' -e 'ssh -p 23 -i /home/yani/.ssh/bx11-xoyize.net -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' /srv/nextcloud-data/ u326239@u326239.your-storagebox.de:backup/xoyize.net/nextcloud-databkp_`date +"%Y%m%d"`/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Sauvegarde base de données MySql</strong></p>
|
|||
|
|
|||
|
<p>Pour un support 4 octets MySQL/MariaDB (Enabling MySQL Support 4 octets, nécessaire pour emoji), vous devrez ajouter <code class="language-plaintext highlighter-rouge">--default-character-set=utf8mb4</code></p>
|
|||
|
|
|||
|
<p>Syntaxe</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mysqldump --single-transaction --default-character-set=utf8mb4 -h [serveur] -u [nom d'utilisateur] -p[mot de passe] [db_name] > nextcloud-sqlbkp_`date +"%Y%m%d"`.bak
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Commande</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># base mysql
|
|||
|
mysqldump --single-transaction --default-character-set=utf8mb4 -h localhost -unextcloud -p`cat /home/yani/.local/share/nextcloud/dbpassword` nextcloud > /home/yani/.local/share/nextcloud/nextcloud-sqlbkp_`date +"%Y%m%d"`.bak
|
|||
|
|
|||
|
# nextcloud database mariadb
|
|||
|
rsync -Aavx --delete --rsync-path='rsync' -e 'ssh -p 23 -i /home/yani/.ssh/bx11-xoyize.net -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' /home/yani/.local/share/nextcloud/nextcloud-sqlbkp_`date +"%Y%m%d"`.bak u326239@u326239.your-storagebox.de:backup/xoyize.net/nextcloud-databkp_`date +"%Y%m%d"`/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="restauration-nextcloud">Restauration nextcloud</h3>
|
|||
|
|
|||
|
<p><a href="https://docs.nextcloud.com/server/latest/admin_manual/maintenance/restore.html">Restauration nextcloud</a></p>
|
|||
|
|
|||
|
<p><strong>Restaurer les dossiers</strong></p>
|
|||
|
|
|||
|
<p>Note : Ce guide suppose que votre sauvegarde précédente est appelée “nextcloud-dirbkp”</p>
|
|||
|
|
|||
|
<p>Il suffit de copier votre dossier de configuration et de données (ou même votre dossier d’installation et de données Nextcloud) dans votre environnement Nextcloud. Vous pouvez utiliser cette commande:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rsync -Aax nextcloud-dirbkp/ nextcloud/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Restaurer la base de données</strong></p>
|
|||
|
|
|||
|
<p>Attention<br />
|
|||
|
Avant de restaurer une sauvegarde, vous devez vous assurer de supprimer toutes les tables de base de données existantes.</p>
|
|||
|
|
|||
|
<p>La manière la plus facile de le faire est de déposer et de recréer la base de données. SQLite le fait automatiquement.</p>
|
|||
|
|
|||
|
<p>MySQL est le moteur de base de données recommandé. Pour restaurer MySQL:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mysql -e "DROP DATABASE nextcloud"
|
|||
|
mysql -e "DROP USER 'nextcloud'@'localhost';"
|
|||
|
mysql -e "CREATE DATABASE nextcloud"
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Si vous utilisez UTF8 avec support multioctet (par exemple pour les emojis dans les noms de fichiers), utilisez:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mysql -e "DROP DATABASE nextcloud"
|
|||
|
mysql -e "CREATE DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci"
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Note Ce guide suppose que votre sauvegarde précédente est appelée «nextcloud-sqlbkp.bak»</p>
|
|||
|
|
|||
|
<p>MySQL est le moteur de base de données recommandé. Pour restaurer MySQL:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mysql -h [serveur] -u [nom d'utilisateur] -p[mot de passe] [db_name]
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="synchronisation-avec-les-clients">Synchronisation avec les clients</h3>
|
|||
|
|
|||
|
<p>après la récupération de données</p>
|
|||
|
|
|||
|
<p>Par défaut, le serveur Nextcloud est considéré comme la source pour les données. Si les données sur le serveur et le client diffèrent, les clients récupèrent par défaut les données sur le serveur.</p>
|
|||
|
|
|||
|
<p>Si la sauvegarde récupérée est dépassée, l’état des clients peut être plus à jour que l’état du serveur. Dans ce cas également assurez-vous de lancer la commande <code class="language-plaintext highlighter-rouge">maintenance:data-fingerprint</code> par la suite. Il modifie la logique de l’algorithme de synchronisation pour essayer de récupérer autant de données que possible. Les fichiers manquants sur le serveur sont donc récupérés auprès des clients et en cas de contenu différent les utilisateurs seront demandés.</p>
|
|||
|
|
|||
|
<p>Note:<br />
|
|||
|
L’utilisation de la maintenance : l’empreinte de données peut provoquer des dialogues de conflit et des difficultés à supprimer des fichiers sur le client. Par conséquent, il est seulement recommandé d’empêcher la perte de données si la sauvegarde a été dépassée.</p>
|
|||
|
|
|||
|
<p>Si vous exécutez plusieurs serveurs d’applications, vous devrez vous assurer que les fichiers de configuration sont synchronisés entre eux de sorte que l’empreinte de données actualisée est appliquée sur tous les cas.</p>
|
|||
|
|
|||
|
<h2 id="scripts-bash-sauvegarde-restauration-nextcloud">Scripts Bash Sauvegarde-Restauration Nextcloud</h2>
|
|||
|
|
|||
|
<p>Scripts Bash pour la sauvegarde/restauration de <a href="https://nextcloud.com/">Nextcloud</a>.</p>
|
|||
|
|
|||
|
<p>Il est basé sur une installation Nextcloud utilisant nginx et PostgreSQL/MariaDB (voir le tutoriel (allemand) <a href="https://decatec.de/home-server/nextcloud-auf-ubuntu-server-22-04-lts-mit-nginx-postgresql-mariadb-php-lets-encrypt-redis-und-fail2ban/">Nextcloud auf Ubuntu Server 22.04 LTS mit nginx, PostgreSQL/MariaDB, PHP, Let’s Encrypt, Redis und Fail2ban</a>).<br />
|
|||
|
<em>Les scripts peuvent également être utilisés lorsqu’Apache est utilisé comme serveur Web.</em></p>
|
|||
|
|
|||
|
<h3 id="informations-générales">Informations générales</h3>
|
|||
|
|
|||
|
<p>Pour une sauvegarde complète de n’importe quelle instance Nextcloud, vous devrez sauvegarder ces éléments :</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>Le répertoire de fichiers Nextcloud (généralement /var/www/nextcloud )</li>
|
|||
|
<li>Le répertoire de données de Nextcloud (il est recommandé qu’il ne se trouve pas à la racine Web, donc par exemple /var/nextcloud_data )</li>
|
|||
|
<li>La base de données Nextcloud</li>
|
|||
|
<li>Eventuellement un stockage externe local monté dans Nextcloud</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Avec ces scripts, tous ces éléments peuvent être inclus dans une sauvegarde.</p>
|
|||
|
|
|||
|
<h3 id="exigences">Exigences</h3>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li><em>tar</em></li>
|
|||
|
<li><em>pigz</em> (https://zlib.net/pigz/) lors de l’utilisation de la compression de sauvegarde. S’il n’est pas déjà installé, il peut être installé avec <code class="language-plaintext highlighter-rouge">apt install pigz</code> (Debian/Ubuntu).<br />
|
|||
|
S’il n’est pas disponible, vous pouvez utiliser un autre algorithme de compression (par exemple gzip)</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h3 id="remarques-importantes-sur-lutilisation-des-scripts">Remarques importantes sur l’utilisation des scripts</h3>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>Après avoir cloné ou téléchargé les scripts, ceux-ci doivent être configurés en exécutant le script setup.sh(voir ci-dessous).</li>
|
|||
|
<li>Si vous ne souhaitez pas utiliser l’installation automatisée, vous pouvez également utiliser le fichier <code class="language-plaintext highlighter-rouge">NextcloudBackupRestore.conf.sample</code> comme point de départ. Assurez-vous simplement de renommer le fichier lorsque vous avez terminé (<code class="language-plaintext highlighter-rouge">cp NextcloudBackupRestore.conf.sample NextcloudBackupRestore.conf</code>)</li>
|
|||
|
<li>Le fichier de configuration <code class="language-plaintext highlighter-rouge">NextcloudBackupRestore.conf</code> doit se trouver dans le même répertoire que les scripts de sauvegarde/restauration.</li>
|
|||
|
<li>Les scripts supposent que le <u>répertoire de données de Nextcloud n'est pas un sous-répertoire de l'installation de Nextcloud</u> (répertoire de fichiers). La recommandation générale est que le répertoire de données ne doit pas se trouver quelque part dans le dossier Web de votre serveur Web (généralement <em>/var/www/</em>), mais dans un dossier différent (par exemple /var/nextcloud_data ). Pour plus d’informations, voir <a href="https://docs.nextcloud.com/server/latest/admin_manual/installation/installation_wizard.html#data-directory-location-label">ici</a>.</li>
|
|||
|
<li>Cependant, si votre répertoire de données se trouve sous le répertoire de fichiers Nextcloud, vous devrez modifier la configuration du script (fichier <code class="language-plaintext highlighter-rouge">NextcloudBackupRestore.conf</code> après exécution <code class="language-plaintext highlighter-rouge">setup.sh</code>) afin que le répertoire de données ne fasse pas partie de la sauvegarde/restauration (sinon, il serait copié deux fois)</li>
|
|||
|
<li>Les scripts sauvegardent uniquement le répertoire de données Nextcloud et peuvent sauvegarder un stockage externe local monté dans Nextcloud. Si vous disposez d’un autre stockage externe monté dans Nextcloud (par exemple FTP), ces fichiers doivent être traités séparément.</li>
|
|||
|
<li>Les scripts prennent en charge nginx et Apache comme serveur Web.</li>
|
|||
|
<li>Les scripts prennent en charge MariaDB/MySQL et PostgreSQL comme base de données.</li>
|
|||
|
<li>Vous devriez avoir activé la prise en charge de 4 octets (voir <a href="https://docs.nextcloud.com/server/latest/admin_manual/configuration_database/mysql_4byte_support.html">Nextcloud Administration Manual</a>) sur votre base de données Nextcloud. Sinon, lorsque vous n’avez pas activé le support 4 octets, vous devez éditer le script de restauration, afin que la base de données ne soit pas créée avec le support 4 octets activé (variable <code class="language-plaintext highlighter-rouge">dbNoMultibyte</code>).</li>
|
|||
|
<li>Les scripts peuvent exclure le répertoire de données Nextcloud de la sauvegarde et de la restauration.
|
|||
|
<strong>ATTENTION</strong> : L’exclusion du répertoire de données n’est <strong>PAS RECOMMANDÉE</strong> car cela laisse la sauvegarde dans un état incohérent et peut entraîner une perte de données !</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h3 id="installation">Installation</h3>
|
|||
|
|
|||
|
<ol>
|
|||
|
<li>Clonez le dépôt: <code class="language-plaintext highlighter-rouge">git clone https://codeberg.org/DecaTec/Nextcloud-Backup-Restore.git</code></li>
|
|||
|
<li>Définir les autorisations:
|
|||
|
<ul>
|
|||
|
<li><code class="language-plaintext highlighter-rouge">chown -R root Nextcloud-Backup-Restore</code></li>
|
|||
|
<li><code class="language-plaintext highlighter-rouge">cd Nextcloud-Backup-Restore</code></li>
|
|||
|
<li><code class="language-plaintext highlighter-rouge">chmod 700 *.sh</code></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li>Appelez le script (interactif) de configuration automatisée (cela créera un fichier <code class="language-plaintext highlighter-rouge">NextcloudBackupRestore.conf</code> contenant la configuration souhaitée): <code class="language-plaintext highlighter-rouge">./setup.sh</code></li>
|
|||
|
<li><strong>Important</strong>: Vérifiez ce fichier de configuration si tout a été configuré correctement (voir TODO dans les commentaires du fichier de configuration)</li>
|
|||
|
<li>Commencez à utiliser les scripts : voir les sections <em>Sauvegarde</em> et <em>restauration</em> ci-dessous</li>
|
|||
|
</ol>
|
|||
|
|
|||
|
<p>Gardez à l’esprit que le fichier de configuration <code class="language-plaintext highlighter-rouge">NextcloudBackupRestore.conf</code> doit être situé dans le même répertoire que les scripts de sauvegarde/restauration, sinon la configuration ne sera pas trouvée.</p>
|
|||
|
|
|||
|
<p>Certaines options facultatives ne sont pas configurées à l’aide de <code class="language-plaintext highlighter-rouge">setup.sh</code>, mais sont définies sur les valeurs par défaut dans <code class="language-plaintext highlighter-rouge">NextcloudBackupRestore.conf</code>. Ce sont les options “dangereuses” qui ne doivent généralement pas être modifiées et qui sont marquées comme ‘OPTIONAL’ dans <code class="language-plaintext highlighter-rouge">NextcloudBackupRestore.conf</code></p>
|
|||
|
|
|||
|
<h3 id="sauvegarde">Sauvegarde</h3>
|
|||
|
|
|||
|
<p>Afin de créer une sauvegarde, appelez simplement le script <em>NextcloudBackup.sh</em> sur votre machine Nextcloud. Si ce script est appelé sans paramètre, la sauvegarde est enregistrée dans un répertoire avec l’horodatage actuel dans votre répertoire de sauvegarde principal : à titre d’exemple, ce serait <em>/media/hdd/nextcloud_backup/20170910_132703</em>. Le script de sauvegarde peut également être appelé avec un paramètre spécifiant le répertoire de sauvegarde principal, par exemple <em>./NextcloudBackup.sh /media/hdd/nextcloud_backup</em>. Dans ce cas, le répertoire spécifié sera utilisé comme répertoire principal de sauvegarde.</p>
|
|||
|
|
|||
|
<p>Vous pouvez également appeler ce script par cron. Exemple (à 2h du matin tous les soirs, avec sortie de journal) :</p>
|
|||
|
|
|||
|
<p><code class="language-plaintext highlighter-rouge">0 2 * * * /path/to/scripts/Nextcloud-Backup-Restore/NextcloudBackup.sh > /path/to/logs/Nextcloud-Backup-$(date +\%Y\%m\%d\%H\%M\%S).log 2>&1</code></p>
|
|||
|
|
|||
|
<h3 id="restauration">Restauration</h3>
|
|||
|
|
|||
|
<p>Appelez <em>NextcloudRestore.sh</em> afin de restaurer une sauvegarde.<br />
|
|||
|
Lorsque ce script est appelé sans paramètres, il répertorie les sauvegardes disponibles pour la restauration. <br />
|
|||
|
Afin de restaurer une sauvegarde, appelez ce script avec un paramètre précisant le nom (c’est-à-dire l’horodatage) de la sauvegarde à restaurer. Dans cet exemple, ce serait <em>20170910_132703</em>. La commande complète pour une restauration serait <em>./NextcloudRestore.sh 20170910_132703</em>.
|
|||
|
Vous pouvez également spécifier le répertoire de sauvegarde principal avec un deuxième paramètre, par exemple <em>./NextcloudRestore.sh 20170910_132703 /media/hdd/nextcloud_backup</em>.</p>
|
|||
|
|
|||
|
<h3 id="mise-à-jour-des-scripts">Mise à jour des scripts</h3>
|
|||
|
|
|||
|
<p>Après avoir mis à jour les scripts vers une version plus récente, il est recommandé d’exécuter (<code class="language-plaintext highlighter-rouge">setup.sh</code>) à nouveau le script de configuration afin de s’assurer que les dernières modifications sont appliquées au fichier de configuration <code class="language-plaintext highlighter-rouge">NextcloudBackupRestore.conf</code>. <br />
|
|||
|
Gardez à l’esprit qu’une version déjà existante de <code class="language-plaintext highlighter-rouge">NextcloudBackupRestore.conf</code> sera écrasée au cours de cette procédure.</p>
|
|||
|
|
|||
|
<p>Il est également recommandé d’exécuter à nouveau le script de configuration si vous souhaitez modifier certains paramètres de base de sauvegarde/restauration (par exemple activer ou désactiver la compression).</p>
|
|||
|
|
|||
|
<h2 id="maintenance">Maintenance</h2>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li><a href="https://docs.nextcloud.com/server/latest/admin_manual/index.html">Nextcloud Server Administration Guide</a></li>
|
|||
|
<li><a href="https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/occ_command.html#">Utiliser les commandes php occ</a></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h3 id="ipv6-mal-identifié">IPV6 mal identifié</h3>
|
|||
|
|
|||
|
<p class="error">Il y a quelques erreurs concernant votre configuration.
|
|||
|
Votre adresse réseau a été identifiée comme « 2a01:e0a:9c8:2080:e4df:3427:584e:b684 » et elle est bridée par le mécanisme anti-intrusion ce qui ralentit la performance de certaines requêtes. Si cette adresse réseau n’est pas la vôtre, cela peut signifier qu’il y a une erreur de configuration d’un proxy.</p>
|
|||
|
|
|||
|
<p>Il faut activer l’application <strong>Brute-force-settings</strong><br />
|
|||
|
<img src="/images/cloud.rnmkcy.eu09.png" alt="" /> <br />
|
|||
|
Puis dans “Paramètres d’administration” , “Sécurité”<br />
|
|||
|
<img src="/images/cloud.rnmkcy.eu10.png" alt="" /></p>
|
|||
|
|
|||
|
<h3 id="base-de-données-index-manquants">Base de données, index manquants</h3>
|
|||
|
|
|||
|
<p class="warning">La base de données a quelques index manquants. L’ajout d’index dans de grandes tables peut prendre un certain temps. Elles ne sont donc pas ajoutées automatiquement. En exécutant “occ db:add-missing-indices”, ces index manquants pourront être ajoutés manuellement pendant que l’instance continue de tourner. Une fois les index ajoutés, les requêtes sur ces tables sont généralement beaucoup plus rapides. Index optionnels manquants « mail_messages_strucanalyz_idx » dans la table « mail_messages ». Index optionnels manquants « mail_class_creat_idx » dans la table « mail_classifiers ». Index optionnels manquants « mail_acc_prov_idx » dans la table « mail_accounts ». Index optionnels manquants « mail_alias_accid_idx » dans la table « mail_aliases ».</p>
|
|||
|
|
|||
|
<p>Procédure pour la correction</p>
|
|||
|
|
|||
|
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo</span> <span class="nt">-s</span>
|
|||
|
<span class="nb">cd</span> /var/www/nextcloud
|
|||
|
<span class="nb">sudo</span> <span class="nt">-u</span> nextcloud /usr/bin/php8.2 occ db:add-missing-indices
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Résultat</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Adding additional mail_messages_strucanalyz_idx index to the oc_mail_messages table, this can take some time...
|
|||
|
oc_mail_messages table updated successfully.
|
|||
|
Adding additional mail_class_creat_idx index to the oc_mail_classifiers table, this can take some time...
|
|||
|
oc_mail_classifiers table updated successfully.
|
|||
|
Adding additional mail_acc_prov_idx index to the oc_mail_accounts table, this can take some time...
|
|||
|
oc_mail_accounts table updated successfully.
|
|||
|
Adding additional mail_alias_accid_idx index to the oc_mail_aliases table, this can take some time...
|
|||
|
oc_mail_aliases table updated successfully.
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ouvrir Nextcloud, <strong>Administration → Vue d’ensemble</strong></p>
|
|||
|
|
|||
|
<h3 id="intégrité-des-fichiers">Intégrité des fichiers</h3>
|
|||
|
|
|||
|
<p><img src="/images/cloud.rnmkcy.eu01 .png" alt="" /><br />
|
|||
|
Liste des fichiers invalides</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Technical information
|
|||
|
=====================
|
|||
|
The following list covers which files have failed the integrity check. Please read
|
|||
|
the previous linked documentation to learn more about the errors and how to fix
|
|||
|
them.
|
|||
|
|
|||
|
Results
|
|||
|
=======
|
|||
|
- core
|
|||
|
- EXTRA_FILE
|
|||
|
- nextcloud.log
|
|||
|
|
|||
|
[...]
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Supprimer les fichiers nextcloud.log et rescanner</p>
|
|||
|
|
|||
|
<h3 id="fichiers-absents-après-mise-à-jour">Fichiers absents après mise à jour</h3>
|
|||
|
|
|||
|
<p>Il arrive parfois que les fichiers n’apparaissent pas après une mise à niveau . Une nouvelle analyse des fichiers peut aider</p>
|
|||
|
|
|||
|
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo</span> <span class="nt">-u</span> www-data php console.php files:scan <span class="nt">--all</span>
|
|||
|
<span class="c"># si nextcloud propriétaire</span>
|
|||
|
<span class="nb">sudo</span> <span class="nt">-u</span> nextcloud php console.php files:scan <span class="nt">--all</span>
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Parfois, Nextcloud peut rester bloqué lors d’une mise à niveau si le processus de mise à niveau basé sur le Web est utilisé. Cela est généralement dû au fait que le processus prend trop de temps et rencontre un délai d’attente PHP.</p>
|
|||
|
|
|||
|
<p>Arrêtez le processus de mise à niveau de cette façon :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -u www-data php occ maintenance:mode --off
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Démarrez ensuite le processus manuel :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -u www-data php occ upgrade
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Si cela ne fonctionne pas correctement, essayez la fonction de réparation :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -u www-data php occ maintenance:repair
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="entretien-de-nextcloud-corbeille-php-et-cache">Entretien de Nextcloud (corbeille, PHP et cache)</h3>
|
|||
|
|
|||
|
<p>En mode sudo : <code class="language-plaintext highlighter-rouge">sudo -s</code></p>
|
|||
|
|
|||
|
<p><strong>Vider la corbeille</strong><br />
|
|||
|
Il peut arriver, lorsque la corbeille devient très chargée, qu’il ne soit plus possible de la vider via l’interface graphique. Dans ce cas-ci, il est recommandé d’utiliser la ligne de commande pour effectuer une vidange manuelle. De plus, cette méthode permet d’accomplir le travail pour plusieurs comptes à la fois, ou même pour l’ensemble de l’installation.</p>
|
|||
|
|
|||
|
<p>Premièrement, on va se positionner dans le répertoire d’installation de Nextcloud, généralement <code class="language-plaintext highlighter-rouge">/var/www/nextcloud</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd /var/www/nextcloud
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Si votre installation est native, l’utilisateur sera <strong>www-data</strong>. Si, par contre, vous utilisez Yunohost, votre utilisateur est <strong>nextcloud</strong>, car il crée des utilisateurs pour chaque application.</p>
|
|||
|
|
|||
|
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">nc_user</span><span class="o">=</span>nextcloud <span class="c"># changer ici au besoin</span>
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Nous allons exécuter la commande suivante pour nettoyer le système de fichiers et la corbeille</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -u ${nc_user} php occ trashbin:cleanup --all-users
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Limiter la durée de rétention des fichiers</strong><br />
|
|||
|
On peut limiter la durée de rétention des fichiers. Pour ce faire, il faut modifier le fichier <code class="language-plaintext highlighter-rouge">/var/www/nextcloud/config/config.php</code><br />
|
|||
|
À la fin du fichier, après la dernière ligne de paramètres, ajouter la ligne suivante:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>'trashbin_retention_obligation' => '30, 35',
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Maintenance automatique</strong><br />
|
|||
|
Nextcloud inclus une routine PHP pour effectuer des tâches de maintenance automatique. Nous pouvons augmenter la fréquence d’exécution en ajoutant cette ligne de commande à la table de CRON de l’utilisateur root. Pour modifier, utiliser cette commande:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo crontab -u ${nc_user} -e
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ajouter la ligne suivante:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>*/15 * * * * php -f /var/www/nextcloud/cron.php
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Nettoyer le cache des fichiers</strong><br />
|
|||
|
Pour nettoyer le cache des fichiers, la commande est similaire à celle utilisée précédemment pour vider la corbeille</p>
|
|||
|
|
|||
|
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo</span> <span class="nt">-u</span> <span class="k">${</span><span class="nv">nc_user</span><span class="k">}</span> php occ files:scan <span class="nt">--all</span>
|
|||
|
<span class="nb">sudo</span> <span class="nt">-u</span> <span class="k">${</span><span class="nv">nc_user</span><span class="k">}</span> php occ files:cleanup
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="erreurs-de-mise-à-jour">Erreurs de mise à jour</h3>
|
|||
|
|
|||
|
<p><strong>Passage Nextcloud Hub 9 (30.0.0)</strong> septembre 2024</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> Detected some missing optional indices. Occasionally new indices are added (by Nextcloud or installed applications) to improve database performance. Adding indices can sometimes take awhile and temporarily hurt performance so this is not done automatically during upgrades. Once the indices are added, queries to those tables should be faster. Use the command `occ db:add-missing-indices` to add them. Index manquants : "fs_name_hash" in table "filecache". Pour plus d’information, voir la documentation ↗.
|
|||
|
|
|||
|
sudo -u nextcloud php occ maintenance:mode --on # Maintenance mode enabled
|
|||
|
sudo -u nextcloud php occ db:add-missing-indices
|
|||
|
sudo -u nextcloud php occ maintenance:mode --off # Maintenance disabled
|
|||
|
|
|||
|
---
|
|||
|
One or more mimetype migrations are available. Occasionally new mimetypes are added to better handle certain file types. Migrating the mimetypes take a long time on larger instances so this is not done automatically during upgrades. Use the command `occ maintenance:repair --include-expensive` to perform the migrations.
|
|||
|
|
|||
|
sudo -u nextcloud php occ maintenance:repair --include-expensive
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>BUG</strong> NON RESOLU le 20/09/2024</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>An exception occured while running the setup check: ValueError: The arguments array must contain 3 items, 1 given in /var/www/nextcloud/lib/private/L10N/L10NString.php:68 Stack trace:
|
|||
|
#0 /var/www/nextcloud/lib/private/L10N/L10NString.php(68): vsprintf()
|
|||
|
#1 /var/www/nextcloud/lib/private/L10N/L10N.php(107): OC\L10N\L10NString->__toString()
|
|||
|
#2 /var/www/nextcloud/lib/private/L10N/LazyL10N.php(38): OC\L10N\L10N->n()
|
|||
|
#3 /var/www/nextcloud/apps/user_ldap/lib/SetupChecks/LdapConnection.php(87): OC\L10N\LazyL10N->n()
|
|||
|
#4 /var/www/nextcloud/lib/private/SetupCheck/SetupCheckManager.php(34): OCA\User_LDAP\SetupChecks\LdapConnection->run()
|
|||
|
#5 /var/www/nextcloud/apps/settings/lib/Controller/CheckSetupController.php(147): OC\SetupCheck\SetupCheckManager->runAll()
|
|||
|
#6 /var/www/nextcloud/lib/private/AppFramework/Http/Dispatcher.php(208): OCA\Settings\Controller\CheckSetupController->check()
|
|||
|
#7 /var/www/nextcloud/lib/private/AppFramework/Http/Dispatcher.php(114): OC\AppFramework\Http\Dispatcher->executeController()
|
|||
|
#8 /var/www/nextcloud/lib/private/AppFramework/App.php(161): OC\AppFramework\Http\Dispatcher->dispatch()
|
|||
|
#9 /var/www/nextcloud/lib/private/Route/Router.php(302): OC\AppFramework\App::main()
|
|||
|
#10 /var/www/nextcloud/lib/base.php(1001): OC\Route\Router->match()
|
|||
|
#11 /var/www/nextcloud/index.php(24): OC::handleRequest()
|
|||
|
#12 {main}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Le(s) lien(s)</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<div class="d-print-none"><footer class="article__footer"><meta itemprop="dateModified" content="2023-09-02T00:00:00+02: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="/2023/09/02/Endeavour_Dell_Latitude_e6230_conteneur_nspawn_debian_bookworm_nspyan.html">EndeavourOS Dell Latitude e6230 --> conteneur nspawn debian bookworm nspyan</a></div><div class="next"><span>SUIVANT</span><a href="/2023/09/12/Economiseur-et-Veille-Ecran-XFCE-xscreensaver.html">Economiseur et veille écran XFCE XScreensaver</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>
|
|||
|
|