mirror of
https://github.com/nextcloud/all-in-one.git
synced 2026-05-21 10:50:10 +00:00
Compare commits
804 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
63a74beeab | ||
|
|
57adc3a137 | ||
|
|
0dd9177630 | ||
|
|
02ec273971 | ||
|
|
70c4223a29 | ||
|
|
79e53f0d00 | ||
|
|
cd6e0ed9d4 | ||
|
|
ac9f86a525 | ||
|
|
675b2025d2 | ||
|
|
8021c8119f | ||
|
|
a58185bb6e | ||
|
|
ce0ede2bcc | ||
|
|
a708102ca7 | ||
|
|
def0509bb3 | ||
|
|
3b2e4a22ae | ||
|
|
478aadf3fa | ||
|
|
443daa092f | ||
|
|
8425fa1b6d | ||
|
|
07d1b5e240 | ||
|
|
bdedc6ab24 | ||
|
|
dd1287469d | ||
|
|
2bf511a935 | ||
|
|
72140ddf36 | ||
|
|
e2ca219cf5 | ||
|
|
6e84405249 | ||
|
|
1a4e5ce3f4 | ||
|
|
5a7aa1cb1f | ||
|
|
45b031545a | ||
|
|
3ce14dc23c | ||
|
|
bc34ab31bc | ||
|
|
dba9980202 | ||
|
|
bd5301cd48 | ||
|
|
e4aff51ea5 | ||
|
|
84dbfc1ed3 | ||
|
|
750c61a8df | ||
|
|
11fdf29fdd | ||
|
|
cfe839f3f6 | ||
|
|
0224304dca | ||
|
|
482b279f3c | ||
|
|
f78620402e | ||
|
|
1b6a3142cd | ||
|
|
71549c49eb | ||
|
|
4db1b278b1 | ||
|
|
1ebb03aef7 | ||
|
|
97f59ac009 | ||
|
|
005ad34741 | ||
|
|
7cc922c18f | ||
|
|
5ece00e496 | ||
|
|
db620e035a | ||
|
|
f99d4f19c6 | ||
|
|
97f053228c | ||
|
|
a26d36c084 | ||
|
|
7ae718300f | ||
|
|
8b7aa71d15 | ||
|
|
8f5966dae9 | ||
|
|
263b5605e1 | ||
|
|
7f245bd048 | ||
|
|
758a721d84 | ||
|
|
49d94b388e | ||
|
|
973ea5ff4f | ||
|
|
0bd376743f | ||
|
|
86f15d0911 | ||
|
|
00c6eeda44 | ||
|
|
9d8990348b | ||
|
|
036bba94c0 | ||
|
|
dfb672811f | ||
|
|
db89be5e9c | ||
|
|
847e5a887c | ||
|
|
dc87c7d3f4 | ||
|
|
bea77e4642 | ||
|
|
e6211d93fe | ||
|
|
2cf98773cc | ||
|
|
85caab7507 | ||
|
|
13beca4072 | ||
|
|
988c37f60b | ||
|
|
d462813e4f | ||
|
|
4a651fc44e | ||
|
|
9d971902d7 | ||
|
|
fb8c2a524d | ||
|
|
95a3323993 | ||
|
|
b454660599 | ||
|
|
21422f2e1c | ||
|
|
3beee36872 | ||
|
|
fc58ec2ac2 | ||
|
|
036c1707d6 | ||
|
|
9b68d3c157 | ||
|
|
fc49283a5e | ||
|
|
cf0b8bdb2a | ||
|
|
62e4ea3238 | ||
|
|
8ff0536705 | ||
|
|
c88696809a | ||
|
|
96888c2ffa | ||
|
|
693df4d4e2 | ||
|
|
ffcace3688 | ||
|
|
4ae556422a | ||
|
|
3de963c238 | ||
|
|
effeb44690 | ||
|
|
4dc2400a87 | ||
|
|
b5d5b1f4bc | ||
|
|
14dbc49863 | ||
|
|
dc4e251b05 | ||
|
|
06779d09ba | ||
|
|
686128c9d4 | ||
|
|
ae056c8c06 | ||
|
|
538f5e5bd3 | ||
|
|
ad751595a8 | ||
|
|
9b1e734efc | ||
|
|
44f6cc0d16 | ||
|
|
aed1cd9700 | ||
|
|
56948a8140 | ||
|
|
66484803c3 | ||
|
|
f0ddf95a3e | ||
|
|
6fe4b99306 | ||
|
|
145d83c000 | ||
|
|
9f6f638d1b | ||
|
|
5d0f344839 | ||
|
|
334c879a5e | ||
|
|
61e1939de4 | ||
|
|
c2c4698119 | ||
|
|
69382b638a | ||
|
|
d5afe84c78 | ||
|
|
bfab40f0d8 | ||
|
|
565f77759f | ||
|
|
bdc07b940f | ||
|
|
9f6821c703 | ||
|
|
ca0371f1f1 | ||
|
|
ad9eadb7f9 | ||
|
|
80d3d71ae9 | ||
|
|
45bb084ae5 | ||
|
|
620ef5ad7f | ||
|
|
a1a9db3404 | ||
|
|
6590f1d12e | ||
|
|
bad431984e | ||
|
|
f5d942f4c9 | ||
|
|
a80f56bb17 | ||
|
|
e5fa3e683b | ||
|
|
8a43baf837 | ||
|
|
b575bf4028 | ||
|
|
ace4410e78 | ||
|
|
f3bd9eba66 | ||
|
|
3c14cc2676 | ||
|
|
bbdb874f90 | ||
|
|
a1a85dde8d | ||
|
|
f73d1e39b4 | ||
|
|
2d9a1afa33 | ||
|
|
3db57c6290 | ||
|
|
3f079bd0f3 | ||
|
|
cf0a5c9cbc | ||
|
|
8764824870 | ||
|
|
703bfa9335 | ||
|
|
141887c635 | ||
|
|
5e9069c450 | ||
|
|
3ff65dda79 | ||
|
|
f470cd8fb5 | ||
|
|
bb4f3e34db | ||
|
|
a1c58d9189 | ||
|
|
fc9d0ce7a3 | ||
|
|
603c980f00 | ||
|
|
f2f816257d | ||
|
|
3358f53b84 | ||
|
|
d15e2d7637 | ||
|
|
39b5925d07 | ||
|
|
12d54ff260 | ||
|
|
81d2a660ec | ||
|
|
a42349f8ec | ||
|
|
1f6b8d48a9 | ||
|
|
7ba10559fd | ||
|
|
af43635fea | ||
|
|
a60ac1bbf4 | ||
|
|
00964ae824 | ||
|
|
f7011b2459 | ||
|
|
c6a356714d | ||
|
|
6240e2e44e | ||
|
|
8dc83171d6 | ||
|
|
709a1315dd | ||
|
|
10d686a44f | ||
|
|
0c2177bead | ||
|
|
4238044199 | ||
|
|
5e1c252b2a | ||
|
|
bdd8f87763 | ||
|
|
66995c9c7b | ||
|
|
f7b04cda0e | ||
|
|
3f5f11dfd9 | ||
|
|
8be1816f92 | ||
|
|
20080daa71 | ||
|
|
abfc70b71d | ||
|
|
22b702f23d | ||
|
|
a53c8442fd | ||
|
|
9e62e7f135 | ||
|
|
56b6425f46 | ||
|
|
f618460a9f | ||
|
|
13ca4c164a | ||
|
|
4740ff1370 | ||
|
|
b371a30531 | ||
|
|
dd18312f68 | ||
|
|
f17ea0f8e4 | ||
|
|
39a40b153a | ||
|
|
331bced264 | ||
|
|
dc8ec276f2 | ||
|
|
76bdd92c7f | ||
|
|
8669f49811 | ||
|
|
f2f70904d1 | ||
|
|
1e82bd757a | ||
|
|
f47a45b07a | ||
|
|
74cdcd27bb | ||
|
|
24c970b184 | ||
|
|
cb24213a31 | ||
|
|
82dd888109 | ||
|
|
4c4080077e | ||
|
|
307d6e0228 | ||
|
|
d42800a7a4 | ||
|
|
3c6cb85c74 | ||
|
|
b4a8322a1a | ||
|
|
3e019d25f2 | ||
|
|
a3d676b408 | ||
|
|
981166d218 | ||
|
|
0498e05f25 | ||
|
|
081f6830f5 | ||
|
|
d0c569ba2f | ||
|
|
3beba0e1a8 | ||
|
|
c8eea9397f | ||
|
|
7a0c9a7f52 | ||
|
|
46ddf8fb86 | ||
|
|
3bf0a769c7 | ||
|
|
c9d7db4dc4 | ||
|
|
216f0a8e9e | ||
|
|
ccddef46b5 | ||
|
|
2b58c544ff | ||
|
|
c64bfd7253 | ||
|
|
d284812c6b | ||
|
|
8d0a2d3199 | ||
|
|
be7d57cf9f | ||
|
|
9ca1946bbc | ||
|
|
7fc49d3f8d | ||
|
|
5aa904fac0 | ||
|
|
86af333662 | ||
|
|
8dc4bd4c43 | ||
|
|
159a46db52 | ||
|
|
4d29c8bf97 | ||
|
|
3054711098 | ||
|
|
1cf5cf5509 | ||
|
|
541e030d89 | ||
|
|
989e11a89e | ||
|
|
c1d08769b4 | ||
|
|
09c0e435ff | ||
|
|
2fd91c0a28 | ||
|
|
b07b365046 | ||
|
|
e50c63df96 | ||
|
|
e2616f79ba | ||
|
|
1bb0fb7006 | ||
|
|
2e92a82a83 | ||
|
|
205887f17d | ||
|
|
02f07bce72 | ||
|
|
a3568cfa00 | ||
|
|
c51f91a446 | ||
|
|
96bf19a162 | ||
|
|
4bf56d7981 | ||
|
|
f07f1e1deb | ||
|
|
929f3415ed | ||
|
|
ac3509e257 | ||
|
|
b08335718d | ||
|
|
2674b61ae7 | ||
|
|
9eded5ae02 | ||
|
|
c6f9d883db | ||
|
|
7d68f2f3ca | ||
|
|
268c647e5f | ||
|
|
bcf051b721 | ||
|
|
74bd6df049 | ||
|
|
31050b559e | ||
|
|
a17682a533 | ||
|
|
7d419695c1 | ||
|
|
d23e138d2a | ||
|
|
cae24e69f8 | ||
|
|
0b6a41f385 | ||
|
|
2fe227de5d | ||
|
|
2faeceb05a | ||
|
|
23b0ea7c8c | ||
|
|
668cc3694a | ||
|
|
3bb97b66a1 | ||
|
|
4695e56011 | ||
|
|
e4f34ef93d | ||
|
|
a2f99636bb | ||
|
|
b003a8b49b | ||
|
|
4e361e3ce2 | ||
|
|
ff27bd77cc | ||
|
|
c152fd7868 | ||
|
|
e5acc9a108 | ||
|
|
195d009c85 | ||
|
|
710b6c562b | ||
|
|
bb36f7e22c | ||
|
|
6d0a68abf3 | ||
|
|
9a0e3eccde | ||
|
|
3449cd61f1 | ||
|
|
b6f22a04f9 | ||
|
|
346824b5e1 | ||
|
|
36797305d8 | ||
|
|
32681c4c95 | ||
|
|
f508e7b33a | ||
|
|
d669a0086c | ||
|
|
5ef9846b61 | ||
|
|
4025ac15ae | ||
|
|
3baaf02969 | ||
|
|
ddf45ad73f | ||
|
|
c5066f2b31 | ||
|
|
3b85396afe | ||
|
|
b9dc1b26d2 | ||
|
|
375ddad429 | ||
|
|
f699c57f07 | ||
|
|
199102918e | ||
|
|
31d369117a | ||
|
|
575150fb92 | ||
|
|
b3b8c85ace | ||
|
|
0bf4538fb9 | ||
|
|
0b0d872c05 | ||
|
|
177477d3cb | ||
|
|
ed646c5cde | ||
|
|
44584431e2 | ||
|
|
8de4655db6 | ||
|
|
9f13f15eb2 | ||
|
|
f732bed008 | ||
|
|
d02ff5fc9f | ||
|
|
b0d83d45a1 | ||
|
|
be9a5f01ea | ||
|
|
895ec0387d | ||
|
|
9f88384f12 | ||
|
|
f110d3e345 | ||
|
|
c6ad842c62 | ||
|
|
99ee0d6744 | ||
|
|
aaf7bcca99 | ||
|
|
84d164de41 | ||
|
|
4759f8fad4 | ||
|
|
ee790d999a | ||
|
|
8ec7bb4af9 | ||
|
|
c5973d9875 | ||
|
|
92bca4f424 | ||
|
|
ae36756476 | ||
|
|
2c4ba5f4a8 | ||
|
|
0a1e2c48e6 | ||
|
|
61cdb6b950 | ||
|
|
d6de2ea76f | ||
|
|
433db49eaf | ||
|
|
9af6a5fe4d | ||
|
|
732c8e7dd9 | ||
|
|
7f82405c8b | ||
|
|
abdb477e8c | ||
|
|
dd19188d6f | ||
|
|
55a2f40eca | ||
|
|
de6a79ab5c | ||
|
|
d53c2b21cb | ||
|
|
3d1cf55f50 | ||
|
|
318310efef | ||
|
|
531f0d7f52 | ||
|
|
3ccc58fefd | ||
|
|
edb987bdb7 | ||
|
|
0659414118 | ||
|
|
82621cccdc | ||
|
|
603ce7cca0 | ||
|
|
8ba392ba0a | ||
|
|
f518ea7fee | ||
|
|
04b51a9467 | ||
|
|
046aad7b1a | ||
|
|
0bd106e44a | ||
|
|
e7c24196ad | ||
|
|
09f9a24fa2 | ||
|
|
d979383993 | ||
|
|
ca47e2d912 | ||
|
|
2b89156bb1 | ||
|
|
316ea5a618 | ||
|
|
8e00812e0d | ||
|
|
e44fbc880b | ||
|
|
77fa851391 | ||
|
|
75446409fb | ||
|
|
249a0e4a55 | ||
|
|
6a1ce7cd2e | ||
|
|
d288bdd023 | ||
|
|
8da25b6c35 | ||
|
|
388dadb587 | ||
|
|
6037b4402b | ||
|
|
933eddae6d | ||
|
|
e28a2c4559 | ||
|
|
1276a1a51f | ||
|
|
73924df349 | ||
|
|
3ad2f2e2b1 | ||
|
|
bad7b8106b | ||
|
|
82784a0297 | ||
|
|
1f26c70865 | ||
|
|
5129fcacdd | ||
|
|
1c0ab8a9e3 | ||
|
|
0b718acf82 | ||
|
|
079a944c07 | ||
|
|
657e384367 | ||
|
|
32862a4d8a | ||
|
|
324d75bbee | ||
|
|
5d787e9167 | ||
|
|
a2047dc04b | ||
|
|
5dfc30afa5 | ||
|
|
301f30dd2c | ||
|
|
dd751a9fe4 | ||
|
|
265c0d563b | ||
|
|
43aba16204 | ||
|
|
324a1156a0 | ||
|
|
d994512140 | ||
|
|
130ca73dd2 | ||
|
|
456f26b9d5 | ||
|
|
37997cc091 | ||
|
|
f3a7dfafa2 | ||
|
|
6be5bb6370 | ||
|
|
a6ffb5495e | ||
|
|
3e59616b5d | ||
|
|
9930a368f0 | ||
|
|
ed319492f1 | ||
|
|
a0cef69483 | ||
|
|
d37a0f509d | ||
|
|
3c34963504 | ||
|
|
460469feb4 | ||
|
|
c642f03d43 | ||
|
|
1c172b4dd7 | ||
|
|
3a79002322 | ||
|
|
8aeee368d4 | ||
|
|
541aa9c6c0 | ||
|
|
627e9d325f | ||
|
|
1c85e3e825 | ||
|
|
c4a8fef8e9 | ||
|
|
76cbefafb5 | ||
|
|
68447c9211 | ||
|
|
810d0590eb | ||
|
|
3c81a90920 | ||
|
|
d2cadf6b9f | ||
|
|
18b3c76a67 | ||
|
|
7312dac0f8 | ||
|
|
dfafec2314 | ||
|
|
947be33fcf | ||
|
|
340f7450ca | ||
|
|
09bbe2fd87 | ||
|
|
e8d66a06d1 | ||
|
|
c66b31901a | ||
|
|
94f0a799fc | ||
|
|
c00a1efdac | ||
|
|
73227b4f9d | ||
|
|
1a65c49331 | ||
|
|
9ce1434f34 | ||
|
|
8a62b4a2ea | ||
|
|
9febf2bade | ||
|
|
098e1347a1 | ||
|
|
74579ba7ea | ||
|
|
5dc4fbdb21 | ||
|
|
931b92b8b9 | ||
|
|
888d16d790 | ||
|
|
21086df922 | ||
|
|
5185a9f4ae | ||
|
|
7eba523e86 | ||
|
|
bcf36406a8 | ||
|
|
abf9684d0d | ||
|
|
cbb5e8f359 | ||
|
|
64c3f61b48 | ||
|
|
936b4ebb0f | ||
|
|
7db547732d | ||
|
|
912fa0697d | ||
|
|
68fd14bc86 | ||
|
|
0d4152a7f9 | ||
|
|
78fc3c1343 | ||
|
|
b4e18256a6 | ||
|
|
f9b13a7786 | ||
|
|
37b33c7f4b | ||
|
|
1f819e403b | ||
|
|
e3826f85b9 | ||
|
|
3e5ab69512 | ||
|
|
7d6695de7e | ||
|
|
06dd83f07a | ||
|
|
cd055c0838 | ||
|
|
1e3bb9ccfe | ||
|
|
7144eb84ff | ||
|
|
def87f38e8 | ||
|
|
0a63b49504 | ||
|
|
e672a5029b | ||
|
|
e22c6d6cef | ||
|
|
2290c0aede | ||
|
|
e448bc1f64 | ||
|
|
fb898b0ab3 | ||
|
|
9cb2801e0f | ||
|
|
d7a528075a | ||
|
|
9c80cc1bb3 | ||
|
|
8d93da24d6 | ||
|
|
faaa59e29a | ||
|
|
3b1014d34d | ||
|
|
3e9b191f94 | ||
|
|
b95bb65af8 | ||
|
|
b72a1c0e59 | ||
|
|
8c7e0bc63a | ||
|
|
f5e8e5630d | ||
|
|
89ff6ea408 | ||
|
|
814f4942f5 | ||
|
|
0941b6dee0 | ||
|
|
ae36403762 | ||
|
|
30eaaaa5f9 | ||
|
|
92a96ca245 | ||
|
|
59a49c62b4 | ||
|
|
0b9108f566 | ||
|
|
7c04f844a1 | ||
|
|
c2056ec215 | ||
|
|
8032f5b966 | ||
|
|
c79d46b868 | ||
|
|
1e7161d524 | ||
|
|
3eede90e86 | ||
|
|
33c822fd1e | ||
|
|
32935d1c33 | ||
|
|
72ca611d2f | ||
|
|
6c6c56fa1b | ||
|
|
6aa0b7097a | ||
|
|
89caf9d725 | ||
|
|
90ba2f7e92 | ||
|
|
55f4a8ec7f | ||
|
|
5f130528ce | ||
|
|
9cffb5a6ee | ||
|
|
164f7026b0 | ||
|
|
a89358ead8 | ||
|
|
31bba7ab80 | ||
|
|
7d49155fc1 | ||
|
|
9dfe5ab770 | ||
|
|
87e018b55f | ||
|
|
fa916c95a7 | ||
|
|
dbef6f1d4a | ||
|
|
fe83acd3cc | ||
|
|
3a0ad6a66f | ||
|
|
1976223efb | ||
|
|
9ff9a7901c | ||
|
|
9c6425308f | ||
|
|
52c926e052 | ||
|
|
1854417c28 | ||
|
|
9cc4393e99 | ||
|
|
cfa207916e | ||
|
|
7586ecefad | ||
|
|
12e30fe316 | ||
|
|
4c50b606bc | ||
|
|
38bd04ded9 | ||
|
|
95ba20d7f9 | ||
|
|
ff042fc742 | ||
|
|
8fedcb4810 | ||
|
|
9a85799220 | ||
|
|
7fc95050d4 | ||
|
|
666064389b | ||
|
|
7c333037fc | ||
|
|
955692a874 | ||
|
|
f2b26d262f | ||
|
|
c46b81da93 | ||
|
|
be0bad4740 | ||
|
|
f40f4a54b6 | ||
|
|
1b86445b6a | ||
|
|
7bcd0c16c0 | ||
|
|
68ac85e60b | ||
|
|
8ce9bd2cc2 | ||
|
|
ea098a4d1a | ||
|
|
b5e45e270b | ||
|
|
1fc8f2dd0f | ||
|
|
8317b30658 | ||
|
|
1a62857df7 | ||
|
|
172ae49cdf | ||
|
|
d385d43af0 | ||
|
|
064ea0f931 | ||
|
|
7f645b1c1a | ||
|
|
38726f039a | ||
|
|
79fdbee6b4 | ||
|
|
4c304d8775 | ||
|
|
8a21f2a8f5 | ||
|
|
1be6c725c2 | ||
|
|
c6d40e91e0 | ||
|
|
4fc4ca1e3e | ||
|
|
31f86c1570 | ||
|
|
a8d380ec7a | ||
|
|
6dd88239d1 | ||
|
|
ead69baae3 | ||
|
|
6be1154914 | ||
|
|
f9772a856c | ||
|
|
83ae27ef76 | ||
|
|
e60949aec9 | ||
|
|
817df30465 | ||
|
|
07ad9a7eb8 | ||
|
|
9c96806084 | ||
|
|
0e1edde3a7 | ||
|
|
8661bdf020 | ||
|
|
c3579476c6 | ||
|
|
ae349b8afb | ||
|
|
20bf2cfa7e | ||
|
|
0cbffeb90a | ||
|
|
8983a97ef6 | ||
|
|
0670c7cedf | ||
|
|
cd00e5af83 | ||
|
|
2c7146b15f | ||
|
|
975f4220d4 | ||
|
|
6beaa3b391 | ||
|
|
6b3cba411e | ||
|
|
ab747de69d | ||
|
|
480b57178b | ||
|
|
c9650aa0ef | ||
|
|
0e660f4c04 | ||
|
|
6722dee1d6 | ||
|
|
79af222c2d | ||
|
|
79473fac76 | ||
|
|
9b11c817b2 | ||
|
|
fb05818764 | ||
|
|
15a289e820 | ||
|
|
d5868a9626 | ||
|
|
22d3b0ba30 | ||
|
|
2b98a936b9 | ||
|
|
3263184e8f | ||
|
|
85b445d576 | ||
|
|
52651559de | ||
|
|
36fd28da6f | ||
|
|
77979aaa4a | ||
|
|
5f753665ac | ||
|
|
e7ec998913 | ||
|
|
91c7f13171 | ||
|
|
d170feb1e7 | ||
|
|
1a55b94b93 | ||
|
|
a0656364b1 | ||
|
|
20c46a3809 | ||
|
|
866519be88 | ||
|
|
cfc157f672 | ||
|
|
8b813fe950 | ||
|
|
c1a5262769 | ||
|
|
5b8de658c7 | ||
|
|
0b51eab553 | ||
|
|
c8854ab1e3 | ||
|
|
7a18cf766d | ||
|
|
213de472a6 | ||
|
|
c9be73601d | ||
|
|
e2a6231257 | ||
|
|
b929d57a77 | ||
|
|
0168b29882 | ||
|
|
8836a884fb | ||
|
|
6adae6db3e | ||
|
|
0071703a24 | ||
|
|
3af23d5a5c | ||
|
|
17eb732a89 | ||
|
|
68ddc72e9b | ||
|
|
a03478c5d0 | ||
|
|
6e8aea3aeb | ||
|
|
2caa883453 | ||
|
|
1edcc4ef5f | ||
|
|
10f62ac401 | ||
|
|
f8f50e9186 | ||
|
|
a3e3dd4534 | ||
|
|
a6286a291f | ||
|
|
2dbd3a5f71 | ||
|
|
c1e2446d22 | ||
|
|
6232000e31 | ||
|
|
7c20d54dd0 | ||
|
|
8ce55a1334 | ||
|
|
853a880c9d | ||
|
|
0ecd2c8f78 | ||
|
|
24d1451325 | ||
|
|
8149c0de75 | ||
|
|
34660f3d17 | ||
|
|
d360031f12 | ||
|
|
efde2ab41a | ||
|
|
a89c183508 | ||
|
|
301b6e6297 | ||
|
|
6e839f5baf | ||
|
|
edb8bd228b | ||
|
|
23429f3e59 | ||
|
|
f4130a8475 | ||
|
|
e5aa3757d5 | ||
|
|
12f1549221 | ||
|
|
d34167b30f | ||
|
|
5e0118a3b5 | ||
|
|
220194b409 | ||
|
|
2943c6cf08 | ||
|
|
2040553822 | ||
|
|
d1656a0fcb | ||
|
|
6e9261f306 | ||
|
|
269f62615f | ||
|
|
704c4ad331 | ||
|
|
9afec142f3 | ||
|
|
9fbcaae567 | ||
|
|
82c371b519 | ||
|
|
2afc711983 | ||
|
|
a42f21555a | ||
|
|
d6ece6cad8 | ||
|
|
6f1da5fc5d | ||
|
|
2024cb8f26 | ||
|
|
1c01e9e21f | ||
|
|
628e55f076 | ||
|
|
5b49faf3b7 | ||
|
|
33a73a7b95 | ||
|
|
e2086ada2b | ||
|
|
c15bc86e06 | ||
|
|
ccc80c44cc | ||
|
|
d12df52864 | ||
|
|
5ed19687e2 | ||
|
|
af93aeebd7 | ||
|
|
aa366556f5 | ||
|
|
a88000095a | ||
|
|
15e914e3f4 | ||
|
|
472334948c | ||
|
|
663901cacd | ||
|
|
6f0e4dc175 | ||
|
|
b0894992b4 | ||
|
|
748dcea39e | ||
|
|
5b278ca261 | ||
|
|
d988706ae0 | ||
|
|
73193ee2d5 | ||
|
|
e955b0a96f | ||
|
|
11edcfe142 | ||
|
|
c779c91ef6 | ||
|
|
3b177a5f55 | ||
|
|
72f7106911 | ||
|
|
cbfe9c1907 | ||
|
|
db12a9a90b | ||
|
|
c777971906 | ||
|
|
0b8caa8cea | ||
|
|
eafe011ae9 | ||
|
|
bc50b0cc4f | ||
|
|
a2f60ba765 | ||
|
|
487688d000 | ||
|
|
30e2c6be25 | ||
|
|
777666cf11 | ||
|
|
221ab2515d | ||
|
|
ac3b8bc963 | ||
|
|
1df46bb805 | ||
|
|
89830a1b81 | ||
|
|
48e60872b3 | ||
|
|
9d9da9e47c | ||
|
|
3a9c305758 | ||
|
|
8f1fcde006 | ||
|
|
8a6de8f63c | ||
|
|
0880aff7ea | ||
|
|
2c3db2fd40 | ||
|
|
e357fc8bb9 | ||
|
|
a82b86b915 | ||
|
|
67705134cf | ||
|
|
ce15c64cd9 | ||
|
|
92492affe4 | ||
|
|
63e0849215 | ||
|
|
1515d0c210 | ||
|
|
4359792a48 | ||
|
|
3887275808 | ||
|
|
badd8d02a9 | ||
|
|
5bc10a56ed | ||
|
|
222dcd3317 | ||
|
|
cec86aa825 | ||
|
|
e7dfb2514b | ||
|
|
b0e570176b | ||
|
|
7756826eb3 | ||
|
|
836552e1a7 | ||
|
|
6e22b364ae | ||
|
|
4979d1d90e | ||
|
|
46d898e196 | ||
|
|
7f034e5109 | ||
|
|
3029b277f1 | ||
|
|
46c754759e | ||
|
|
1339be5045 | ||
|
|
53f5b4ae11 | ||
|
|
de7f47e973 | ||
|
|
b08a06573d | ||
|
|
44d491cc5b | ||
|
|
96b381bcab | ||
|
|
7b40e6b733 | ||
|
|
ed56f37c4c | ||
|
|
baa5f5635b | ||
|
|
ff59c30604 | ||
|
|
1a6253ee4c | ||
|
|
8af877f048 | ||
|
|
02c8b57d4e | ||
|
|
0052582003 | ||
|
|
7bb0c3b164 | ||
|
|
ddd01be82f | ||
|
|
c585548c07 | ||
|
|
3de828034a | ||
|
|
bb3bcad752 | ||
|
|
0748ee9fbf | ||
|
|
a2f01c2fcf | ||
|
|
4b28a6a7d7 | ||
|
|
0bf050a51f | ||
|
|
b9ab319357 | ||
|
|
46c5c59e5b | ||
|
|
ad5e3c3f51 | ||
|
|
98cb4e9494 | ||
|
|
37f219300b | ||
|
|
d934629889 | ||
|
|
285e093e57 | ||
|
|
2be5cb255b | ||
|
|
7159cd387a | ||
|
|
3041e51b04 | ||
|
|
4e852761d9 | ||
|
|
20d631b600 | ||
|
|
b4c58941ed | ||
|
|
d7b7a013fd | ||
|
|
d65ffed5b1 | ||
|
|
3ea0799eb5 | ||
|
|
c48a0de6d2 | ||
|
|
7a6ed91a3e | ||
|
|
8bdcba11e6 | ||
|
|
d19069c8e3 | ||
|
|
095fc6de2b | ||
|
|
f8ac6bb865 | ||
|
|
400e575972 | ||
|
|
61bd306416 | ||
|
|
d27c33cdce | ||
|
|
a95f36d673 | ||
|
|
0c543c0ad4 | ||
|
|
2a3eab9ea6 | ||
|
|
aa1e4d3eef | ||
|
|
6dd9e06a5f | ||
|
|
3d8d7f0d79 |
32
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
Normal file
32
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: 🐛 Bug report
|
||||
about: Help us improving by reporting a bug
|
||||
labels: bug, 0. Needs triage
|
||||
---
|
||||
|
||||
<!--- Please keep this note for other contributors -->
|
||||
### How to use GitHub
|
||||
|
||||
* Please use the 👍 [reaction](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) to show that you are affected by the same issue.
|
||||
* Please don't comment if you have no relevant information to add. It's just extra noise for everyone subscribed to this issue.
|
||||
* Subscribe to receive notifications on status change and new comments.
|
||||
|
||||
<!--- Please fill out the whole template below -->
|
||||
### Steps to reproduce
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
### Expected behavior <!--- Tell us what should happen -->
|
||||
|
||||
### Actual behavior <!--- Tell us what happens instead -->
|
||||
|
||||
|
||||
### Host OS <!--- (the host OS on which you are trying to install AIO on) -->
|
||||
|
||||
|
||||
#### Nextcloud AIO version <!--- (see Nextcloud AIO interface) -->
|
||||
|
||||
#### Current channel <!--- (see the channel name in the AIO interface) -->
|
||||
|
||||
#### Other valuable info <!--- (like logs, screenshots & Co.) -->
|
||||
24
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
Normal file
24
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
name: 📖 Existing feature/documentation enhancement
|
||||
about: Suggest an enhancement of an existing feature/documentation - for other types, please use the feature request option below
|
||||
labels: enhancement, 0. Needs triage
|
||||
---
|
||||
|
||||
<!--- Please keep this note for other contributors -->
|
||||
### How to use GitHub
|
||||
* Please use the 👍 [reaction](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) to show that you are interested into the same feature.
|
||||
* Please don't comment if you have no relevant information to add. It's just extra noise for everyone subscribed to this issue.
|
||||
* Subscribe to receive notifications on status change and new comments.
|
||||
|
||||
<!--- Please fill out the whole template below -->
|
||||
### Is your feature request related to a problem? Please describe.
|
||||
<!--- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
|
||||
|
||||
### Describe the solution you'd like
|
||||
<!--- A clear and concise description of what you want to happen. -->
|
||||
|
||||
### Describe alternatives you've considered
|
||||
<!--- A clear and concise description of any alternative solutions or features you've considered. -->
|
||||
|
||||
### Additional context
|
||||
<!--- Add any other context or screenshots about the feature request below. -->
|
||||
14
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
14
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 💡 Suggest a new feature or discuss one
|
||||
url: https://github.com/nextcloud/all-in-one/discussions/categories/ideas
|
||||
about: For new feature requests and discussion of existing ones
|
||||
- name: ❓ Questions on AIO
|
||||
url: https://github.com/nextcloud/all-in-one/discussions/categories/questions
|
||||
about: For questions regarding AIO
|
||||
- name: ⛑️ Community Support and Help
|
||||
url: https://help.nextcloud.com/tag/aio
|
||||
about: For other types of questions
|
||||
- name: 💼 Nextcloud Enterprise
|
||||
url: https://portal.nextcloud.com/
|
||||
about: If you are a Nextcloud Enterprise customer, or need Professional support, so it can be resolved directly by our dedicated engineers more quickly
|
||||
132
.github/dependabot.yml
vendored
132
.github/dependabot.yml
vendored
@@ -1,12 +1,136 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
time: "12:00"
|
||||
open-pull-requests-limit: 10
|
||||
- package-ecosystem: composer
|
||||
directory: "/php/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: saturday
|
||||
time: "03:00"
|
||||
timezone: Europe/Paris
|
||||
interval: "daily"
|
||||
time: "12:00"
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/Containers/apache"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
time: "12:00"
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/Containers/borgbackup"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
time: "12:00"
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/Containers/collabora"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
time: "12:00"
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/Containers/domaincheck"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
time: "12:00"
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/Containers/mastercontainer"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
time: "12:00"
|
||||
ignore:
|
||||
- dependency-name: "php"
|
||||
update-types: ["version-update:semver-major", "version-update:semver-minor"]
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/Containers/nextcloud"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
time: "12:00"
|
||||
ignore:
|
||||
- dependency-name: "php"
|
||||
update-types: ["version-update:semver-major", "version-update:semver-minor"]
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/Containers/postgresql"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
time: "12:00"
|
||||
ignore:
|
||||
- dependency-name: "postgres"
|
||||
update-types: ["version-update:semver-major"]
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/Containers/redis"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
time: "12:00"
|
||||
ignore:
|
||||
- dependency-name: "redis"
|
||||
update-types: ["version-update:semver-major"]
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/Containers/talk"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
time: "12:00"
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/Containers/watchtower"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
time: "12:00"
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/Containers/clamav"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
time: "12:00"
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/Containers/onlyoffice"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
time: "12:00"
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 3. to review
|
||||
|
||||
54
.github/workflows/create-psalm-container.yml
vendored
Normal file
54
.github/workflows/create-psalm-container.yml
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
name: Create Psalm Container
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '5 4 * * *'
|
||||
|
||||
jobs:
|
||||
push_to_registry:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
name: Create Psalm Container
|
||||
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
run: |
|
||||
git clone https://github.com/psalm/psalm-github-actions.git
|
||||
|
||||
- name: Modify the Dockerfile
|
||||
run: |
|
||||
set -x
|
||||
sed -i 's|FROM php:7.4-alpine|FROM php:8.0-alpine|' "psalm-github-actions/Dockerfile"
|
||||
cat << APCU >> "psalm-github-actions/Dockerfile"
|
||||
RUN mkdir -p /usr/src/php/ext/apcu && \
|
||||
curl -fsSL https://pecl.php.net/get/apcu | tar xvz -C "/usr/src/php/ext/apcu" --strip 1 && \
|
||||
docker-php-ext-install apcu
|
||||
APCU
|
||||
|
||||
- name: Log in to GitHub Docker Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: docker.pkg.github.com
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build container image
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
push: true
|
||||
context: 'psalm-github-actions'
|
||||
file: 'psalm-github-actions/Dockerfile'
|
||||
tags: |
|
||||
ghcr.io/nextcloud/all-in-one-psalm:latest
|
||||
19
.github/workflows/dependency-updates.yml
vendored
19
.github/workflows/dependency-updates.yml
vendored
@@ -9,18 +9,21 @@ jobs:
|
||||
name: Run dependency update script
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: nanasess/setup-php@master
|
||||
with:
|
||||
php-version: '8.0'
|
||||
- name: Run dependency update script
|
||||
run: |
|
||||
set -x
|
||||
curl -sS https://getcomposer.org/installer | php
|
||||
mv composer.phar /usr/local/bin/composer
|
||||
chmod +x /usr/local/bin/composer
|
||||
cd ./php
|
||||
composer update
|
||||
set +e
|
||||
ALL_LINES="$(composer outdated | grep -v "psr/container")"
|
||||
set -e
|
||||
while [ -n "$ALL_LINES" ]; do
|
||||
CURRENT_LINE="$(echo "$ALL_LINES" | head -1)"
|
||||
composer require "$(echo "$CURRENT_LINE" | awk '{print $1}')" "^$(echo "$CURRENT_LINE" | awk '{print $4}')"
|
||||
@@ -28,8 +31,20 @@ jobs:
|
||||
done
|
||||
echo "outdated dependencies:
|
||||
$(composer outdated)"
|
||||
- name: Update apcu
|
||||
run: |
|
||||
# APCU
|
||||
apcu_version="$(
|
||||
git ls-remote --tags https://github.com/krakjoe/apcu.git \
|
||||
| cut -d/ -f3 \
|
||||
| grep -viE -- 'rc|b' \
|
||||
| sed -E 's/^v//' \
|
||||
| sort -V \
|
||||
| tail -1
|
||||
)"
|
||||
sed -i "s|pecl install APCu.*\;|pecl install APCu-$apcu_version\;|" ./Containers/mastercontainer/Dockerfile
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v3
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
commit-message: dependency updates
|
||||
signoff: true
|
||||
|
||||
20
.github/workflows/json-validator.yml
vendored
Normal file
20
.github/workflows/json-validator.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
name: Json Validator
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
psalm:
|
||||
name: Json Validator
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- name: Validate Json
|
||||
run: |
|
||||
sudo apt install python3-pip --no-install-recommends
|
||||
sudo pip3 install json-spec
|
||||
json validate --schema-file=php/containers-schema.json --document-file=php/containers.json
|
||||
48
.github/workflows/lint-php.yml
vendored
Normal file
48
.github/workflows/lint-php.yml
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
# This workflow is provided via the organization template repository
|
||||
#
|
||||
# https://github.com/nextcloud/.github
|
||||
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||
|
||||
name: Lint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
- stable*
|
||||
|
||||
jobs:
|
||||
php-lint:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
php-versions: ["8.0"]
|
||||
|
||||
name: php-lint
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up php ${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
coverage: none
|
||||
|
||||
- name: Lint
|
||||
run: cd php && composer run lint
|
||||
|
||||
summary:
|
||||
runs-on: ubuntu-latest
|
||||
needs: php-lint
|
||||
|
||||
if: always()
|
||||
|
||||
name: php-lint-summary
|
||||
|
||||
steps:
|
||||
- name: Summary status
|
||||
run: if ${{ needs.php-lint.result != 'success' && needs.php-lint.result != 'skipped' }}; then exit 1; fi
|
||||
20
.github/workflows/lock-threads.yml
vendored
Normal file
20
.github/workflows/lock-threads.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
name: 'Lock Threads'
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
concurrency:
|
||||
group: lock
|
||||
|
||||
jobs:
|
||||
action:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v3
|
||||
with:
|
||||
issue-inactive-days: '14'
|
||||
process-only: 'issues'
|
||||
11
.github/workflows/nextcloud-update.yml
vendored
11
.github/workflows/nextcloud-update.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
name: Run nextcloud-update script
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Run nextcloud-update script
|
||||
run: |
|
||||
# Inspired by https://github.com/nextcloud/docker/blob/master/update.sh
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
apcu_version="$(
|
||||
git ls-remote --tags https://github.com/krakjoe/apcu.git \
|
||||
| cut -d/ -f3 \
|
||||
| grep -vE -- '-rc|-b' \
|
||||
| grep -viE -- 'rc|b' \
|
||||
| sed -E 's/^v//' \
|
||||
| sort -V \
|
||||
| tail -1
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
memcached_version="$(
|
||||
git ls-remote --tags https://github.com/php-memcached-dev/php-memcached.git \
|
||||
| cut -d/ -f3 \
|
||||
| grep -vE -- '-rc|-b' \
|
||||
| grep -viE -- 'rc|b' \
|
||||
| sed -E 's/^[rv]//' \
|
||||
| sort -V \
|
||||
| tail -1
|
||||
@@ -60,11 +60,12 @@ jobs:
|
||||
sed -i "s|pecl install imagick.*\;|pecl install imagick-$imagick_version\;|" ./Containers/nextcloud/Dockerfile
|
||||
|
||||
# Nextcloud
|
||||
NCVERSION=$(curl -s -m 900 https://download.nextcloud.com/server/releases/ | sed --silent 's/.*href="nextcloud-\([^"]\+\).zip.asc".*/\1/p' | sort --version-sort | tail -1)
|
||||
NC_MAJOR="$(grep "ENV NEXTCLOUD_VERSION" ./Containers/nextcloud/Dockerfile | grep -oP '[23][0-9]')"
|
||||
NCVERSION=$(curl -s -m 900 https://download.nextcloud.com/server/releases/ | sed --silent 's/.*href="nextcloud-\([^"]\+\).zip.asc".*/\1/p' | grep "$NC_MAJOR" | sort --version-sort | tail -1)
|
||||
sed -i "s|^ENV NEXTCLOUD_VERSION.*|ENV NEXTCLOUD_VERSION $NCVERSION|" ./Containers/nextcloud/Dockerfile
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v3
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
commit-message: nextcloud-update automated change
|
||||
signoff: true
|
||||
|
||||
28
.github/workflows/psalm-analysis.yml
vendored
Normal file
28
.github/workflows/psalm-analysis.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: Psalm Analysis
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
psalm:
|
||||
name: Psalm
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up php8.0
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: 8.0
|
||||
extensions: apcu
|
||||
coverage: none
|
||||
|
||||
- name: Run script
|
||||
run: |
|
||||
set -x
|
||||
cd php
|
||||
composer global require vimeo/psalm --prefer-dist --no-progress --dev
|
||||
composer install
|
||||
composer run psalm
|
||||
25
.github/workflows/psalm-security.yml
vendored
Normal file
25
.github/workflows/psalm-security.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
name: Psalm Security Analysis
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
psalm:
|
||||
name: Psalm
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- name: Psalm
|
||||
uses: docker://ghcr.io/nextcloud/all-in-one-psalm
|
||||
with:
|
||||
relative_dir: php
|
||||
security_analysis: true
|
||||
composer_ignore_platform_reqs: false
|
||||
report_file: results.sarif
|
||||
- name: Upload Security Analysis results to GitHub
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: php/results.sarif
|
||||
48
.github/workflows/psalm-update-baseline.yml
vendored
Normal file
48
.github/workflows/psalm-update-baseline.yml
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
name: Update Psalm baseline
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '5 4 * * *'
|
||||
|
||||
jobs:
|
||||
update-psalm-baseline:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up php8.0
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: 8.0
|
||||
extensions: apcu
|
||||
coverage: none
|
||||
|
||||
- name: Run script
|
||||
run: |
|
||||
set -x
|
||||
cd php
|
||||
composer global require vimeo/psalm --prefer-dist --no-progress --dev
|
||||
composer install
|
||||
composer run psalm -- --monochrome --no-progress --output-format=text --update-baseline
|
||||
git clean -f lib/composer
|
||||
git checkout composer.json composer.lock lib/composer
|
||||
continue-on-error: true
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
token: ${{ secrets.COMMAND_BOT_PAT }}
|
||||
commit-message: Update psalm baseline
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: nextcloud-command <nextcloud-command@users.noreply.github.com>
|
||||
signoff: true
|
||||
branch: automated/noid/psalm-baseline-update
|
||||
# Make sure we can open multiple PRs
|
||||
branch-suffix: timestamp
|
||||
title: '[Automated] Update psalm-baseline.xml'
|
||||
body: |
|
||||
Auto-generated update psalm-baseline.xml with fixed psalm warnings
|
||||
labels: |
|
||||
3. to review
|
||||
20
.github/workflows/shellcheck.yml
vendored
Normal file
20
.github/workflows/shellcheck.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
name: Shellcheck
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
shellcheck:
|
||||
name: Github Actions
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Run Shellcheck
|
||||
uses: ludeeus/action-shellcheck@master
|
||||
with:
|
||||
check_together: 'yes'
|
||||
env:
|
||||
SHELLCHECK_OPTS: --shell bash
|
||||
23
.github/workflows/spellcheck.yml
vendored
Normal file
23
.github/workflows/spellcheck.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: 'Spellcheck'
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
spellcheck:
|
||||
name: Check spelling
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: spelling or typos
|
||||
uses: actions/checkout@v3
|
||||
- name: fix permission for reviewdog
|
||||
run: sudo chown -R root:root $GITHUB_WORKSPACE
|
||||
- name: misspell
|
||||
uses: reviewdog/action-misspell@v1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
locale: "US"
|
||||
fail_on_error: true
|
||||
27
.github/workflows/update-yaml.yml
vendored
Normal file
27
.github/workflows/update-yaml.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
name: Update Yaml files
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '00 12 * * *'
|
||||
|
||||
jobs:
|
||||
psalm:
|
||||
name: update yaml files
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- name: update yaml files
|
||||
run: |
|
||||
sudo bash manual-install/update-yaml.sh
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
commit-message: Yaml updates
|
||||
signoff: true
|
||||
title: Yaml updates
|
||||
body: Automated yaml updates for the docker-compose files. Should only be merged shortly before the next latest release.
|
||||
labels: dependencies
|
||||
milestone: next
|
||||
branch: aio-yaml-update
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,3 +3,6 @@
|
||||
/php/data/configuration.json
|
||||
/php/data/backupsecret.json
|
||||
/php/vendor
|
||||
/manual-install/*.conf
|
||||
!/manual-install/sample.conf
|
||||
/manual-install/docker-compose.yml
|
||||
@@ -1 +1 @@
|
||||
* @szaimen @LukasReschke @azul @juliushaertl
|
||||
* @szaimen @juliushaertl
|
||||
|
||||
@@ -6,40 +6,48 @@
|
||||
}
|
||||
}
|
||||
|
||||
https://{$NC_DOMAIN}:443 {
|
||||
{$PROTOCOL}://{$NC_DOMAIN}:{$APACHE_PORT} {
|
||||
|
||||
# Notify Push
|
||||
route /push/* {
|
||||
uri strip_prefix /push
|
||||
reverse_proxy {$NEXTCLOUD_HOST}:7867
|
||||
reverse_proxy {$NEXTCLOUD_HOST}:7867 {
|
||||
# trusted_proxies placeholder
|
||||
}
|
||||
}
|
||||
|
||||
# Talk
|
||||
route /standalone-signaling/* {
|
||||
uri strip_prefix /standalone-signaling
|
||||
reverse_proxy {$TALK_HOST}:8081
|
||||
reverse_proxy {$TALK_HOST}:8081 {
|
||||
# trusted_proxies placeholder
|
||||
}
|
||||
}
|
||||
|
||||
# Collabora
|
||||
route /browser/* {
|
||||
reverse_proxy https://{$COLLABORA_HOST}:9980 {
|
||||
transport http {
|
||||
tls_insecure_skip_verify
|
||||
}
|
||||
reverse_proxy {$COLLABORA_HOST}:9980 {
|
||||
# trusted_proxies placeholder
|
||||
}
|
||||
}
|
||||
route /hosting/* {
|
||||
reverse_proxy https://{$COLLABORA_HOST}:9980 {
|
||||
transport http {
|
||||
tls_insecure_skip_verify
|
||||
}
|
||||
reverse_proxy {$COLLABORA_HOST}:9980 {
|
||||
# trusted_proxies placeholder
|
||||
}
|
||||
}
|
||||
route /cool/* {
|
||||
reverse_proxy https://{$COLLABORA_HOST}:9980 {
|
||||
transport http {
|
||||
tls_insecure_skip_verify
|
||||
}
|
||||
reverse_proxy {$COLLABORA_HOST}:9980 {
|
||||
# trusted_proxies placeholder
|
||||
}
|
||||
}
|
||||
|
||||
# Onlyoffice
|
||||
route /onlyoffice/* {
|
||||
uri strip_prefix /onlyoffice
|
||||
reverse_proxy {$ONLYOFFICE_HOST}:80 {
|
||||
header_up X-Forwarded-Host {http.request.host}/onlyoffice
|
||||
header_up X-Forwarded-Proto https
|
||||
# trusted_proxies placeholder
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +56,10 @@ https://{$NC_DOMAIN}:443 {
|
||||
rewrite /.well-known/carddav /remote.php/dav
|
||||
rewrite /.well-known/caldav /remote.php/dav
|
||||
header Strict-Transport-Security max-age=31536000;
|
||||
reverse_proxy localhost:80
|
||||
reverse_proxy localhost:8000 {
|
||||
# See https://github.com/nextcloud/all-in-one/issues/828
|
||||
# trusted_proxies placeholder
|
||||
}
|
||||
}
|
||||
|
||||
# TLS options
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
FROM debian:bullseye
|
||||
# Caddy is a requirement
|
||||
FROM caddy:2.5.2-alpine as caddy
|
||||
|
||||
EXPOSE 80
|
||||
FROM debian:bullseye-20220711-slim
|
||||
|
||||
RUN mkdir -p /mnt/data; \
|
||||
chown www-data:www-data /mnt/data;
|
||||
@@ -21,10 +22,8 @@ RUN set -ex; \
|
||||
; \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN set -ex; \
|
||||
wget "https://caddyserver.com/api/download?os=linux&arch=$(dpkg-architecture --query DEB_BUILD_ARCH)" -O "/usr/bin/caddy" \
|
||||
&& chmod +x /usr/bin/caddy \
|
||||
&& /usr/bin/caddy version
|
||||
COPY --from=caddy /usr/bin/caddy /usr/bin/
|
||||
RUN chmod +x /usr/bin/caddy
|
||||
|
||||
RUN a2enmod rewrite \
|
||||
headers \
|
||||
@@ -39,12 +38,17 @@ RUN a2enmod rewrite \
|
||||
|
||||
COPY nextcloud.conf /etc/apache2/sites-available/
|
||||
|
||||
RUN a2dissite 000-default && \
|
||||
RUN rm /etc/apache2/ports.conf; \
|
||||
sed -s -i -e "s/Include ports.conf//" /etc/apache2/apache2.conf; \
|
||||
sed -i "/^Listen /d" /etc/apache2/apache2.conf
|
||||
|
||||
RUN set -ex; \
|
||||
a2dissite 000-default && \
|
||||
a2dissite default-ssl && \
|
||||
a2ensite nextcloud.conf && \
|
||||
rm -rf /var/www/html/* && \
|
||||
service apache2 restart; \
|
||||
chown www-data:www-data -R /var/log/apache2; \
|
||||
mkdir -p /var/run/apache2; \
|
||||
chown -R www-data:www-data /var/run/apache2; \
|
||||
chown -R www-data:www-data /var/www;
|
||||
|
||||
@@ -59,7 +63,8 @@ COPY start.sh /usr/bin/
|
||||
COPY supervisord.conf /
|
||||
RUN chmod +x /usr/bin/start.sh; \
|
||||
chmod +r /supervisord.conf; \
|
||||
chmod +r /Caddyfile;
|
||||
chown www-data:www-data /Caddyfile; \
|
||||
chmod +r -R /etc/apache2
|
||||
|
||||
# Give root a random password
|
||||
RUN echo "root:$(openssl rand -base64 12)" | chpasswd
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<VirtualHost *:80>
|
||||
Listen 8000
|
||||
<VirtualHost *:8000>
|
||||
# PHP match
|
||||
<FilesMatch "\.php$">
|
||||
SetHandler "proxy:fcgi://nextcloud-aio-nextcloud:9000"
|
||||
@@ -19,4 +20,8 @@
|
||||
<Files ".ht*">
|
||||
Require all denied
|
||||
</Files>
|
||||
|
||||
# Fix zero file sizes
|
||||
# See https://github.com/nextcloud/server/issues/3056#issuecomment-954209565
|
||||
SetEnv proxy-sendcl 1
|
||||
</VirtualHost>
|
||||
|
||||
@@ -17,11 +17,33 @@ while ! nc -z "$NEXTCLOUD_HOST" 9000; do
|
||||
sleep 5
|
||||
done
|
||||
|
||||
# Only start container if collabora is started
|
||||
while ! nc -z "$COLLABORA_HOST" 9980; do
|
||||
echo "Waiting for Collabora to start..."
|
||||
sleep 5
|
||||
done
|
||||
if [ -z "$APACHE_PORT" ]; then
|
||||
export APACHE_PORT="443"
|
||||
fi
|
||||
|
||||
# Change variables in case of reverse proxies
|
||||
if [ "$APACHE_PORT" != '443' ]; then
|
||||
export PROTOCOL="http"
|
||||
export NC_DOMAIN=""
|
||||
else
|
||||
export PROTOCOL="https"
|
||||
fi
|
||||
|
||||
# Change the auto_https in case of reverse proxies
|
||||
if [ "$APACHE_PORT" != '443' ]; then
|
||||
CADDYFILE="$(sed 's|auto_https.*|auto_https off|' /Caddyfile)"
|
||||
else
|
||||
CADDYFILE="$(sed 's|auto_https.*|auto_https disable_redirects|' /Caddyfile)"
|
||||
fi
|
||||
echo "$CADDYFILE" > /Caddyfile
|
||||
|
||||
# Change the trusted_proxies in case of reverse proxies
|
||||
if [ "$APACHE_PORT" != '443' ]; then
|
||||
CADDYFILE="$(sed 's|# trusted_proxies placeholder|trusted_proxies private_ranges|' /Caddyfile)"
|
||||
else
|
||||
CADDYFILE="$(sed 's|trusted_proxies private_ranges|# trusted_proxies placeholder|' /Caddyfile)"
|
||||
fi
|
||||
echo "$CADDYFILE" > /Caddyfile
|
||||
|
||||
# Add caddy path
|
||||
mkdir -p /mnt/data/caddy/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM debian:bullseye
|
||||
FROM debian:bullseye-20220711-slim
|
||||
|
||||
RUN set -ex; \
|
||||
\
|
||||
@@ -8,6 +8,7 @@ RUN set -ex; \
|
||||
rsync \
|
||||
fuse \
|
||||
python3-llfuse \
|
||||
jq \
|
||||
; \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Variables
|
||||
BORG_BACKUP_DIRECTORY="/mnt/borgbackup/borg"
|
||||
|
||||
# Functions
|
||||
get_start_time(){
|
||||
START_TIME=$(date +%s)
|
||||
CURRENT_DATE=$(date --date @"$START_TIME" +"%Y%m%d_%H%M%S")
|
||||
CURRENT_DATE_READABLE=$(date --date @"$START_TIME" +"%d.%m.%Y - %H:%M:%S")
|
||||
}
|
||||
get_expiration_time() {
|
||||
END_TIME=$(date +%s)
|
||||
@@ -19,11 +15,6 @@ get_expiration_time() {
|
||||
DURATION_READABLE=$(printf "%02d hours %02d minutes %02d seconds" $DURATION_HOUR $DURATION_MIN $DURATION_SEC)
|
||||
}
|
||||
|
||||
# Export defaults
|
||||
export BORG_PASSPHRASE="$BORG_PASSWORD"
|
||||
export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes
|
||||
export BORG_RELOCATED_REPO_ACCESS_IS_OK=yes
|
||||
|
||||
# Test if all volumes aren't empty
|
||||
VOLUME_DIRS="$(find /nextcloud_aio_volumes -mindepth 1 -maxdepth 1 -type d)"
|
||||
mapfile -t VOLUME_DIRS <<< "$VOLUME_DIRS"
|
||||
@@ -41,18 +32,16 @@ if ! mountpoint -q /mnt/borgbackup; then
|
||||
fi
|
||||
|
||||
# Check if target is empty
|
||||
if [ "$BORG_MODE" != backup ] && ! [ -f "$BORG_BACKUP_DIRECTORY/config" ]; then
|
||||
if [ "$BORG_MODE" != backup ] && [ "$BORG_MODE" != test ] && ! [ -f "$BORG_BACKUP_DIRECTORY/config" ]; then
|
||||
echo "The repository is empty. cannot perform check or restore."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Break the borg lock if it exists
|
||||
if [ -f "$BORG_BACKUP_DIRECTORY/lock.roster" ]; then
|
||||
echo "Breaking the borg lock..."
|
||||
if ! borg break-lock "$BORG_BACKUP_DIRECTORY"; then
|
||||
echo "Could not break the borg lock!"
|
||||
exit 1
|
||||
fi
|
||||
# Do not continue if this file exists (needed for simple external blocking)
|
||||
if [ -f "$BORG_BACKUP_DIRECTORY/aio-lockfile" ]; then
|
||||
echo "Not continuing because aio-lockfile exists - it seems like a script is externally running which is locking the backup archive."
|
||||
echo "If this should not be the case, you can fix this by deleting the 'aio-lockfile' file from the backup archive directory."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create lockfile
|
||||
@@ -150,9 +139,6 @@ if [ "$BORG_MODE" = backup ]; then
|
||||
# Remove the update skip file because the backup was successful
|
||||
rm -f "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/skip.update"
|
||||
|
||||
echo "$CURRENT_DATE,$CURRENT_DATE_READABLE" >> "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/backup_archives.list"
|
||||
chmod +r "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/backup_archives.list"
|
||||
|
||||
# Prune options
|
||||
BORG_PRUNE_OPTS=(--stats --progress --keep-within=7d --keep-weekly=4 --keep-monthly=6 "$BORG_BACKUP_DIRECTORY")
|
||||
|
||||
@@ -172,27 +158,71 @@ fi
|
||||
# Do the restore
|
||||
if [ "$BORG_MODE" = restore ]; then
|
||||
get_start_time
|
||||
echo "Restoring the last backup..."
|
||||
|
||||
# Perform the restore
|
||||
FIRST_ARCHIVE="$(borg list "$BORG_BACKUP_DIRECTORY" | grep "nextcloud-aio" | awk -F " " '{print $1}' | sort -r | head -1)"
|
||||
if [ -n "$SELECTED_RESTORE_TIME" ]; then
|
||||
SELECTED_ARCHIVE="$(borg list "$BORG_BACKUP_DIRECTORY" | grep "nextcloud-aio" | grep "$SELECTED_RESTORE_TIME" | awk -F " " '{print $1}' | head -1)"
|
||||
else
|
||||
SELECTED_ARCHIVE="$(borg list "$BORG_BACKUP_DIRECTORY" | grep "nextcloud-aio" | awk -F " " '{print $1}' | sort -r | head -1)"
|
||||
fi
|
||||
echo "Restoring '$SELECTED_ARCHIVE'..."
|
||||
mkdir -p /tmp/borg
|
||||
if ! borg mount "$BORG_BACKUP_DIRECTORY::$FIRST_ARCHIVE" /tmp/borg; then
|
||||
if ! borg mount "$BORG_BACKUP_DIRECTORY::$SELECTED_ARCHIVE" /tmp/borg; then
|
||||
echo "Could not mount the backup!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Restore everything except the configuration file
|
||||
if ! rsync --stats --archive --human-readable -vv --delete \
|
||||
--exclude "nextcloud_aio_mastercontainer/data/backup_archives.list" \
|
||||
--exclude "nextcloud_aio_mastercontainer/session/"** \
|
||||
--exclude "nextcloud_aio_mastercontainer/certs/"** \
|
||||
--exclude "nextcloud_aio_mastercontainer/data/daily_backup_running" \
|
||||
--exclude "nextcloud_aio_mastercontainer/data/configuration.json" \
|
||||
/tmp/borg/nextcloud_aio_volumes/ /nextcloud_aio_volumes; then
|
||||
echo "Something failed while restoring the boot partition."
|
||||
echo "Something failed while restoring from backup."
|
||||
umount /tmp/borg
|
||||
exit 1
|
||||
fi
|
||||
umount /tmp/borg
|
||||
|
||||
# TODO: reset fetchtimes in configuration.json so that it doesn't get the latest directly...
|
||||
# Save current aio password
|
||||
AIO_PASSWORD="$(jq '.password' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)"
|
||||
|
||||
# Save current path
|
||||
BORG_LOCATION="$(jq '.borg_backup_host_location' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)"
|
||||
|
||||
# Save current nextcloud datadir
|
||||
if grep -q '"nextcloud_datadir":' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json; then
|
||||
NEXTCLOUD_DATADIR="$(jq '.nextcloud_datadir' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)"
|
||||
else
|
||||
NEXTCLOUD_DATADIR='""'
|
||||
fi
|
||||
|
||||
# Restore the configuration file
|
||||
if ! rsync --archive --human-readable -vv \
|
||||
/tmp/borg/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json \
|
||||
/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json; then
|
||||
echo "Something failed while restoring the configuration.json."
|
||||
umount /tmp/borg
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set backup-mode to restore since it was a restore
|
||||
CONTENTS="$(jq '."backup-mode" = "restore"' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)"
|
||||
echo -E "${CONTENTS}" > /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json
|
||||
|
||||
# Reset the backup path to the currently used one
|
||||
CONTENTS="$(jq ".borg_backup_host_location = $BORG_LOCATION" /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)"
|
||||
echo -E "${CONTENTS}" > /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json
|
||||
|
||||
# Reset the AIO password to the currently used one
|
||||
CONTENTS="$(jq ".password = $AIO_PASSWORD" /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)"
|
||||
echo -E "${CONTENTS}" > /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json
|
||||
|
||||
# Reset the datadir to the one that was used for the restore
|
||||
CONTENTS="$(jq ".nextcloud_datadir = $NEXTCLOUD_DATADIR" /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)"
|
||||
echo -E "${CONTENTS}" > /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json
|
||||
|
||||
umount /tmp/borg
|
||||
|
||||
# Inform user
|
||||
get_expiration_time
|
||||
@@ -202,16 +232,15 @@ if [ "$BORG_MODE" = restore ]; then
|
||||
touch "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/skip.update"
|
||||
chmod 777 "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/skip.update"
|
||||
|
||||
# Set backup-mode to restore since it was a restore
|
||||
sed -i 's/"backup-mode":"[a-z]\+"/"backup-mode":"restore"/g' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json
|
||||
|
||||
exit 0
|
||||
# Add file to Nextcloud container so that it performs a fingerprint update the next time
|
||||
touch "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/fingerprint.update"
|
||||
chmod 777 "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/fingerprint.update"
|
||||
fi
|
||||
|
||||
# Do the Backup check
|
||||
if [ "$BORG_MODE" = check ]; then
|
||||
get_start_time
|
||||
echo "Checking the backup integity..."
|
||||
echo "Checking the backup integrity..."
|
||||
|
||||
# Perform the check
|
||||
if ! borg check --verify-data --progress "$BORG_BACKUP_DIRECTORY"; then
|
||||
@@ -224,3 +253,27 @@ if [ "$BORG_MODE" = check ]; then
|
||||
echo "Check finished successfully on $END_DATE_READABLE ($DURATION_READABLE)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Do the backup test
|
||||
if [ "$BORG_MODE" = test ]; then
|
||||
if ! [ -d "$BORG_BACKUP_DIRECTORY" ]; then
|
||||
echo "No 'borg' directory in the given backup directory found!"
|
||||
echo "Only the files/folders below have been found in the given directory."
|
||||
ls -a "$MOUNT_DIR"
|
||||
echo "Please adjust the directory so that the borg archive is positioned in a folder named 'borg' inside the given directory!"
|
||||
exit 1
|
||||
elif ! [ -f "$BORG_BACKUP_DIRECTORY/config" ]; then
|
||||
echo "A 'borg' directory was found but could not find the borg archive."
|
||||
echo "Only the files/folders below have been found in the borg directory."
|
||||
ls -a "$BORG_BACKUP_DIRECTORY"
|
||||
echo "The archive and most importantly the config file must be positioned directly in the 'borg' subfolder."
|
||||
exit 1
|
||||
elif ! borg list "$BORG_BACKUP_DIRECTORY"; then
|
||||
echo "The entered path seems to be valid but could not open the backup archive."
|
||||
echo "Most likely the entered password was wrong so please adjust it accordingly!"
|
||||
exit 1
|
||||
else
|
||||
echo "Everything looks fine so feel free to continue!"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1,16 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Variables
|
||||
export MOUNT_DIR="/mnt/borgbackup"
|
||||
export BORG_BACKUP_DIRECTORY="$MOUNT_DIR/borg"
|
||||
|
||||
# Validate BORG_PASSWORD
|
||||
if [ -z "$BORG_PASSWORD" ]; then
|
||||
echo "BORG_PASSWORD is not allowed to be empty."
|
||||
if [ -z "$BORG_PASSWORD" ] && [ -z "$BACKUP_RESTORE_PASSWORD" ]; then
|
||||
echo "Neither BORG_PASSWORD nor BACKUP_RESTORE_PASSWORD are set."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export BORG_PASSWORD
|
||||
# Export defaults
|
||||
if [ -n "$BACKUP_RESTORE_PASSWORD" ]; then
|
||||
export BORG_PASSPHRASE="$BACKUP_RESTORE_PASSWORD"
|
||||
else
|
||||
export BORG_PASSPHRASE="$BORG_PASSWORD"
|
||||
fi
|
||||
export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes
|
||||
export BORG_RELOCATED_REPO_ACCESS_IS_OK=yes
|
||||
|
||||
# Validate BORG_MODE
|
||||
if [ "$BORG_MODE" != backup ] && [ "$BORG_MODE" != restore ] && [ "$BORG_MODE" != check ]; then
|
||||
echo "No correct BORG_MODE mode applied. Valid are 'backup' and 'restore'."
|
||||
if [ "$BORG_MODE" != backup ] && [ "$BORG_MODE" != restore ] && [ "$BORG_MODE" != check ] && [ "$BORG_MODE" != test ]; then
|
||||
echo "No correct BORG_MODE mode applied. Valid are 'backup', 'check', 'restore' and 'test'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -24,6 +35,14 @@ fi
|
||||
# Remove lockfile
|
||||
rm -f "/nextcloud_aio_volumes/nextcloud_aio_database_dump/backup-is-running"
|
||||
|
||||
# Get a list of all available borg archives
|
||||
if borg list "$BORG_BACKUP_DIRECTORY" &>/dev/null; then
|
||||
borg list "$BORG_BACKUP_DIRECTORY" | grep "nextcloud-aio" | awk -F " " '{print $1","$3,$4}' > "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/backup_archives.list"
|
||||
else
|
||||
echo "" > "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/backup_archives.list"
|
||||
fi
|
||||
chmod +r "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/backup_archives.list"
|
||||
|
||||
if [ -n "$FAILED" ]; then
|
||||
if [ "$BORG_MODE" = backup ]; then
|
||||
# Add file to Nextcloud container so that it skips any update the next time
|
||||
|
||||
6
Containers/clamav/Dockerfile
Normal file
6
Containers/clamav/Dockerfile
Normal file
@@ -0,0 +1,6 @@
|
||||
# Probably from this file: https://github.com/Cisco-Talos/clamav/blob/main/Dockerfile
|
||||
FROM clamav/clamav:0.104.2-3
|
||||
|
||||
RUN apk add --update --no-cache tzdata
|
||||
COPY clamav.conf /tmp/
|
||||
RUN cat /tmp/clamav.conf >> /etc/clamav/clamd.conf
|
||||
4
Containers/clamav/clamav.conf
Normal file
4
Containers/clamav/clamav.conf
Normal file
@@ -0,0 +1,4 @@
|
||||
MaxDirectoryRecursion 30
|
||||
MaxFileSize 100M
|
||||
PCREMaxFileSize 100M
|
||||
StreamMaxLength 100M
|
||||
@@ -1,2 +1,15 @@
|
||||
# From a file located probably somewhere here: https://github.com/CollaboraOnline/online/tree/master/docker
|
||||
FROM collabora/code:latest
|
||||
FROM collabora/code:22.05.4.1.1
|
||||
|
||||
USER root
|
||||
|
||||
RUN set -ex; \
|
||||
\
|
||||
apt-get update; \
|
||||
export DEBIAN_FRONTEND=noninteractive; \
|
||||
apt-get install -y --no-install-recommends \
|
||||
tzdata \
|
||||
; \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
USER 104
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
FROM alpine
|
||||
FROM alpine:3.15.4
|
||||
RUN apk add --update --no-cache lighttpd bash
|
||||
|
||||
RUN adduser -S www-data -G www-data
|
||||
RUN rm -rf /etc/lighttpd/lighttpd.conf
|
||||
COPY lighttpd.conf /etc/lighttpd/lighttpd.conf
|
||||
RUN chmod +r -R /etc/lighttpd && \
|
||||
chown www-data:www-data -R /var/www
|
||||
chown www-data:www-data -R /var/www && \
|
||||
chown www-data:www-data /etc/lighttpd/lighttpd.conf
|
||||
|
||||
COPY start.sh /
|
||||
RUN chmod +x /start.sh
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
server.document-root = "/var/www/domaincheck/"
|
||||
|
||||
server.port = 443
|
||||
server.port = env.APACHE_PORT
|
||||
|
||||
server.username = "www-data"
|
||||
server.groupname = "www-data"
|
||||
@@ -13,4 +13,8 @@ mimetype.assign = (
|
||||
)
|
||||
|
||||
static-file.exclude-extensions = ( ".fcgi", ".php", ".rb", "~", ".inc" )
|
||||
index-file.names = ( "index.html" )
|
||||
index-file.names = ( "index.html" )
|
||||
|
||||
$SERVER["socket"] == "ipv6-placeholder" {
|
||||
server.document-root = "/var/www/domaincheck/"
|
||||
}
|
||||
|
||||
@@ -7,6 +7,13 @@ fi
|
||||
|
||||
echo "$INSTANCE_ID" > /var/www/domaincheck/index.html
|
||||
|
||||
if [ -z "$APACHE_PORT" ]; then
|
||||
export APACHE_PORT="443"
|
||||
fi
|
||||
|
||||
CONF_FILE="$(sed "s|ipv6-placeholder|\[::\]:$APACHE_PORT|" /etc/lighttpd/lighttpd.conf)"
|
||||
echo "$CONF_FILE" > /etc/lighttpd/lighttpd.conf
|
||||
|
||||
# Check config file
|
||||
lighttpd -tt -f /etc/lighttpd/lighttpd.conf
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
{
|
||||
# auto_https will create redirects for https://{host}:8443 instead of https://{host}
|
||||
# https redirects are added manually in the http://:80 block
|
||||
auto_https disable_redirects
|
||||
|
||||
storage file_system {
|
||||
@@ -6,6 +8,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
http://:80 {
|
||||
redir https://{host}{uri}
|
||||
}
|
||||
|
||||
https://:8443 {
|
||||
|
||||
reverse_proxy localhost:8000
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# Docker CLI is a requirement
|
||||
FROM docker:20.10.17-dind-alpine3.16 as dind
|
||||
|
||||
# Caddy is a requirement
|
||||
FROM caddy:2.5.2-alpine as caddy
|
||||
|
||||
# From https://github.com/docker-library/php/blob/master/8.0/bullseye/apache/Dockerfile
|
||||
FROM php:8.0-apache-bullseye
|
||||
FROM php:8.0.21-apache-bullseye
|
||||
|
||||
EXPOSE 80
|
||||
EXPOSE 8080
|
||||
@@ -20,23 +26,26 @@ RUN apt-get update; \
|
||||
openssl \
|
||||
sudo \
|
||||
dpkg-dev \
|
||||
netcat \
|
||||
; \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN set -ex; \
|
||||
curl "https://caddyserver.com/api/download?os=linux&arch=$(dpkg-architecture --query DEB_BUILD_ARCH)" -o "/usr/bin/caddy" \
|
||||
&& chmod +x /usr/bin/caddy \
|
||||
&& /usr/bin/caddy version
|
||||
COPY --from=caddy /usr/bin/caddy /usr/bin/
|
||||
RUN chmod +x /usr/bin/caddy
|
||||
|
||||
COPY --from=docker:dind /usr/local/bin/docker /usr/local/bin/
|
||||
COPY --from=dind /usr/local/bin/docker /usr/local/bin/
|
||||
RUN chmod +x /usr/local/bin/docker
|
||||
|
||||
RUN set -ex; \
|
||||
pecl install APCu-5.1.21; \
|
||||
docker-php-ext-enable apcu
|
||||
|
||||
RUN set -e && \
|
||||
curl -sS https://getcomposer.org/installer | php && \
|
||||
mv composer.phar /usr/local/bin/composer && \
|
||||
chmod +x /usr/local/bin/composer && \
|
||||
cd /var/www/docker-aio; \
|
||||
git clone https://github.com/nextcloud/all-in-one.git --depth 1 .; \
|
||||
git clone https://github.com/nextcloud-releases/all-in-one.git --depth 1 .; \
|
||||
cd php; \
|
||||
composer install --no-dev; \
|
||||
composer clearcache; \
|
||||
@@ -74,16 +83,19 @@ RUN a2dissite 000-default && \
|
||||
RUN mkdir /var/log/supervisord; \
|
||||
mkdir /var/run/supervisord;
|
||||
|
||||
RUN mkdir -p /usr/src/php/ext/apcu && \
|
||||
curl -fsSL https://pecl.php.net/get/apcu | tar xvz -C "/usr/src/php/ext/apcu" --strip 1 && \
|
||||
docker-php-ext-install apcu
|
||||
|
||||
COPY Caddyfile /
|
||||
COPY start.sh /usr/bin/
|
||||
COPY backup-time-file-watcher.sh /
|
||||
COPY session-deduplicator.sh /
|
||||
COPY cron.sh /
|
||||
COPY daily-backup.sh /
|
||||
COPY supervisord.conf /
|
||||
RUN chmod +x /usr/bin/start.sh; \
|
||||
chmod +x /cron.sh
|
||||
chmod +x /cron.sh; \
|
||||
chmod +x /session-deduplicator.sh; \
|
||||
chmod +x /backup-time-file-watcher.sh; \
|
||||
chmod +x /daily-backup.sh; \
|
||||
chmod a+r /Caddyfile
|
||||
|
||||
USER root
|
||||
|
||||
|
||||
30
Containers/mastercontainer/backup-time-file-watcher.sh
Normal file
30
Containers/mastercontainer/backup-time-file-watcher.sh
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
restart_process() {
|
||||
echo "Restarting cron.sh because daily backup time was set, changed or unset."
|
||||
pkill cron.sh
|
||||
}
|
||||
|
||||
file_present() {
|
||||
if [ -f "/mnt/docker-aio-config/data/daily_backup_time" ]; then
|
||||
if [ "$FILE_PRESENT" = 0 ]; then
|
||||
restart_process
|
||||
else
|
||||
if [ -n "$BACKUP_TIME" ] && [ "$(head -1 "/mnt/docker-aio-config/data/daily_backup_time")" != "$BACKUP_TIME" ]; then
|
||||
restart_process
|
||||
fi
|
||||
fi
|
||||
FILE_PRESENT=1
|
||||
BACKUP_TIME="$(head -1 "/mnt/docker-aio-config/data/daily_backup_time")"
|
||||
else
|
||||
if [ "$FILE_PRESENT" = 1 ]; then
|
||||
restart_process
|
||||
fi
|
||||
FILE_PRESENT=0
|
||||
fi
|
||||
}
|
||||
|
||||
while true; do
|
||||
file_present
|
||||
sleep 2
|
||||
done
|
||||
@@ -1,10 +1,52 @@
|
||||
#!/bin/sh
|
||||
set -eux
|
||||
#!/bin/bash
|
||||
|
||||
while true; do
|
||||
if [ -f "/mnt/docker-aio-config/data/daily_backup_time" ]; then
|
||||
set -x
|
||||
BACKUP_TIME="$(head -1 "/mnt/docker-aio-config/data/daily_backup_time")"
|
||||
export BACKUP_TIME
|
||||
export DAILY_BACKUP=1
|
||||
if [ "$(sed -n '2p' "/mnt/docker-aio-config/data/daily_backup_time")" != 'automaticUpdatesAreNotEnabled' ]; then
|
||||
export AUTOMATIC_UPDATES=1
|
||||
else
|
||||
export AUTOMATIC_UPDATES=0
|
||||
export START_CONTAINERS=1
|
||||
fi
|
||||
set +x
|
||||
else
|
||||
export BACKUP_TIME="04:00"
|
||||
export DAILY_BACKUP=0
|
||||
fi
|
||||
|
||||
if [ -f "/mnt/docker-aio-config/data/daily_backup_running" ]; then
|
||||
export LOCK_FILE_PRESENT=1
|
||||
else
|
||||
export LOCK_FILE_PRESENT=0
|
||||
fi
|
||||
|
||||
# Allow to continue directly if e.g. the mastercontainer was updated. Otherwise wait for the next execution
|
||||
if [ "$LOCK_FILE_PRESENT" = 0 ]; then
|
||||
while [ "$(date +%H:%M)" != "$BACKUP_TIME" ]; do
|
||||
sleep 30
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$DAILY_BACKUP" = 1 ]; then
|
||||
bash /daily-backup.sh
|
||||
fi
|
||||
|
||||
# Make sure to delete the lock file always
|
||||
rm -f "/mnt/docker-aio-config/data/daily_backup_running"
|
||||
|
||||
# Check for updates and send notification if yes
|
||||
sudo -u www-data php /var/www/docker-aio/php/src/Cron/cron.php
|
||||
sudo -u www-data php /var/www/docker-aio/php/src/Cron/UpdateNotification.php
|
||||
|
||||
# Remove sessions older than 24h
|
||||
find "/mnt/docker-aio-config/session/" -mindepth 1 -mmin +1440 -delete
|
||||
|
||||
# Remove dangling images
|
||||
sudo -u www-data docker image prune -f
|
||||
sleep 1d
|
||||
|
||||
# Wait 60s so that the whole loop will not be executed again
|
||||
sleep 60
|
||||
done
|
||||
|
||||
77
Containers/mastercontainer/daily-backup.sh
Normal file
77
Containers/mastercontainer/daily-backup.sh
Normal file
@@ -0,0 +1,77 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "Daily backup has started"
|
||||
|
||||
# Delete all active sessions and create a lock file
|
||||
# But don't kick out the user if the mastercontainer was just updated since we block the interface either way with the lock file
|
||||
if [ "$LOCK_FILE_PRESENT" = 0 ]; then
|
||||
rm -f "/mnt/docker-aio-config/session/"*
|
||||
fi
|
||||
sudo -u www-data touch "/mnt/docker-aio-config/data/daily_backup_running"
|
||||
|
||||
# Check if apache is running/stopped, watchtower is stopped and backupcontainer is stopped
|
||||
APACHE_PORT="$(docker inspect nextcloud-aio-apache --format "{{.HostConfig.PortBindings}}" | grep -oP '[0-9]+' | head -1)"
|
||||
while docker ps --format "{{.Names}}" | grep -q "^nextcloud-aio-apache$" && ! nc -z nextcloud-aio-apache "$APACHE_PORT"; do
|
||||
echo "Waiting for apache to become available"
|
||||
sleep 30
|
||||
done
|
||||
while docker ps --format "{{.Names}}" | grep -q "^nextcloud-aio-watchtower$"; do
|
||||
echo "Waiting for watchtower to stop"
|
||||
sleep 30
|
||||
done
|
||||
while docker ps --format "{{.Names}}" | grep -q "^nextcloud-aio-borgbackup$"; do
|
||||
echo "Waiting for borgbackup to stop"
|
||||
sleep 30
|
||||
done
|
||||
|
||||
# Update the mastercontainer
|
||||
if [ "$AUTOMATIC_UPDATES" = 1 ]; then
|
||||
sudo -u www-data php /var/www/docker-aio/php/src/Cron/UpdateMastercontainer.php
|
||||
fi
|
||||
|
||||
# Wait for watchtower to stop
|
||||
if [ "$AUTOMATIC_UPDATES" = 1 ] && ! docker ps --format "{{.Names}}" | grep -q "^nextcloud-aio-watchtower$"; then
|
||||
echo "Something seems to be wrong: Watchtower should be started at this step."
|
||||
else
|
||||
while docker ps --format "{{.Names}}" | grep -q "^nextcloud-aio-watchtower$"; do
|
||||
echo "Waiting for watchtower to stop"
|
||||
sleep 30
|
||||
done
|
||||
fi
|
||||
|
||||
# Stop containers if required
|
||||
if [ "$DAILY_BACKUP" != 1 ] || [ "$STOP_CONTAINERS" = 1 ]; then
|
||||
sudo -u www-data php /var/www/docker-aio/php/src/Cron/StopContainers.php
|
||||
fi
|
||||
|
||||
# Execute the backup itself and some related tasks (also stops the containers)
|
||||
if [ "$DAILY_BACKUP" = 1 ]; then
|
||||
sudo -u www-data php /var/www/docker-aio/php/src/Cron/CreateBackup.php
|
||||
fi
|
||||
|
||||
# Start and/or update containers
|
||||
if [ "$AUTOMATIC_UPDATES" = 1 ]; then
|
||||
sudo -u www-data php /var/www/docker-aio/php/src/Cron/StartAndUpdateContainers.php
|
||||
else
|
||||
if [ "$START_CONTAINERS" = 1 ]; then
|
||||
sudo -u www-data php /var/www/docker-aio/php/src/Cron/StartContainers.php
|
||||
fi
|
||||
fi
|
||||
|
||||
# Delete the lock file
|
||||
rm -f "/mnt/docker-aio-config/data/daily_backup_running"
|
||||
|
||||
if [ "$DAILY_BACKUP" = 1 ]; then
|
||||
# Wait for the nextcloud container to start and send if the backup was successful
|
||||
if ! docker ps --format "{{.Names}}" | grep -q "^nextcloud-aio-nextcloud$"; then
|
||||
echo "Something seems to be wrong: Nextcloud should be started at this step."
|
||||
else
|
||||
while docker ps --format "{{.Names}}" | grep -q "^nextcloud-aio-nextcloud$" && ! nc -z nextcloud-aio-nextcloud 9000; do
|
||||
echo "Waiting for the Nextcloud container to start"
|
||||
sleep 30
|
||||
done
|
||||
fi
|
||||
sudo -u www-data php /var/www/docker-aio/php/src/Cron/BackupNotification.php
|
||||
fi
|
||||
|
||||
echo "Daily backup has finished"
|
||||
@@ -44,3 +44,7 @@ ErrorLog ${APACHE_LOG_DIR}/error.log
|
||||
SSLEngine on
|
||||
SSLProtocol -all +TLSv1.2 +TLSv1.3
|
||||
</VirtualHost>
|
||||
|
||||
# Increase timeout in case e.g. the initial download takes a long time
|
||||
Timeout 7200
|
||||
ProxyTimeout 7200
|
||||
|
||||
23
Containers/mastercontainer/session-deduplicator.sh
Normal file
23
Containers/mastercontainer/session-deduplicator.sh
Normal file
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
|
||||
while true; do
|
||||
while [ "$(find "/mnt/docker-aio-config/session/" -mindepth 1 -exec grep "aio_authenticated|[a-z]:1" {} \; | wc -l)" -gt 1 ]; do
|
||||
unset SESSION_FILES
|
||||
SESSION_FILES="$(find "/mnt/docker-aio-config/session/" -mindepth 1)"
|
||||
unset SESSION_FILES_ARRAY
|
||||
mapfile -t SESSION_FILES_ARRAY <<< "$SESSION_FILES"
|
||||
for SESSION_FILE in "${SESSION_FILES_ARRAY[@]}"; do
|
||||
if ! grep -q "aio_authenticated|[a-z]:1" "$SESSION_FILE"; then
|
||||
rm "$SESSION_FILE"
|
||||
fi
|
||||
done
|
||||
echo "Deleting duplicate sessions"
|
||||
unset OLDEST_FILE
|
||||
set -x
|
||||
# shellcheck disable=SC2012
|
||||
OLDEST_FILE="$(ls -t "/mnt/docker-aio-config/session/" | tail -1)"
|
||||
rm "/mnt/docker-aio-config/session/$OLDEST_FILE"
|
||||
set +x
|
||||
done
|
||||
sleep 5
|
||||
done
|
||||
@@ -6,6 +6,14 @@ print_green() {
|
||||
printf "%b%s%b\n" "\e[0;92m" "$TEXT" "\e[0m"
|
||||
}
|
||||
|
||||
# Function to check if number was provided
|
||||
check_if_number() {
|
||||
case "${1}" in
|
||||
''|*[!0-9]*) return 1 ;;
|
||||
*) return 0 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Check if socket is available and readable
|
||||
if ! [ -a "/var/run/docker.sock" ]; then
|
||||
echo "Docker socket is not available. Cannot continue."
|
||||
@@ -23,6 +31,9 @@ elif ! sudo -u www-data test -r /var/run/docker.sock; then
|
||||
echo "Adding internal www-data to group $DOCKER_GROUP"
|
||||
usermod -aG "$DOCKER_GROUP" www-data
|
||||
else
|
||||
# Delete the docker group for cases when the docker socket permissions changed between restarts
|
||||
groupdel docker &>/dev/null
|
||||
|
||||
# If the group doesn't exist, create it
|
||||
echo "Creating docker group internally with id $DOCKER_GROUP_ID"
|
||||
groupadd -g "$DOCKER_GROUP_ID" docker
|
||||
@@ -35,17 +46,18 @@ elif ! sudo -u www-data test -r /var/run/docker.sock; then
|
||||
fi
|
||||
|
||||
# Check if api version is supported
|
||||
if ! docker info &>/dev/null; then
|
||||
if ! sudo -u www-data docker info &>/dev/null; then
|
||||
echo "Cannot connect to the docker socket. Cannot proceed."
|
||||
exit 1
|
||||
fi
|
||||
API_VERSION_FILE="$(find ./ -name DockerActionManager.php | head -1)"
|
||||
API_VERSION="$(grep -oP 'const API_VERSION.*\;' "$API_VERSION_FILE" | grep -oP [0-9]+.[0-9]+ | head -1)"
|
||||
API_VERSION="$(grep -oP 'const API_VERSION.*\;' "$API_VERSION_FILE" | grep -oP '[0-9]+.[0-9]+' | head -1)"
|
||||
# shellcheck disable=SC2001
|
||||
API_VERSION_NUMB="$(echo "$API_VERSION" | sed 's/\.//')"
|
||||
LOCAL_API_VERSION_NUMB="$(docker version | grep -i "api version" | grep -oP [0-9]+.[0-9]+ | head -1 | sed 's/\.//')"
|
||||
LOCAL_API_VERSION_NUMB="$(sudo -u www-data docker version | grep -i "api version" | grep -oP '[0-9]+.[0-9]+' | head -1 | sed 's/\.//')"
|
||||
if [ -n "$LOCAL_API_VERSION_NUMB" ] && [ -n "$API_VERSION_NUMB" ]; then
|
||||
if ! [ "$LOCAL_API_VERSION_NUMB" -ge "$API_VERSION_NUMB" ]; then
|
||||
echo "Docker v$API_VERSION is not supported by your docker engine. Cannot proceed."
|
||||
echo "Docker API v$API_VERSION is not supported by your docker engine. Cannot proceed. Please upgrade your docker engine if you want to run Nextcloud AIO!"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
@@ -53,6 +65,97 @@ else
|
||||
sleep 10
|
||||
fi
|
||||
|
||||
# Check if startup command was executed correctly
|
||||
if ! sudo -u www-data docker ps | grep -q "nextcloud-aio-mastercontainer"; then
|
||||
echo "It seems like you did not give the mastercontainer the correct name?
|
||||
Using a different name is not supported!"
|
||||
exit 1
|
||||
elif ! sudo -u www-data docker volume ls | grep -q "nextcloud_aio_mastercontainer"; then
|
||||
echo "It seems like you did not give the mastercontainer volume the correct name?
|
||||
Using a different name is not supported!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for other options
|
||||
if [ -n "$NEXTCLOUD_DATADIR" ]; then
|
||||
if [ "$NEXTCLOUD_DATADIR" = "nextcloud_aio_nextcloud_datadir" ]; then
|
||||
echo "NEXTCLOUD_DATADIR is set to $NEXTCLOUD_DATADIR"
|
||||
elif ! echo "$NEXTCLOUD_DATADIR" | grep -q "^/" || [ "$NEXTCLOUD_DATADIR" = "/" ]; then
|
||||
echo "You've set NEXTCLOUD_DATADIR but not to an allowed value.
|
||||
The string must start with '/' and must not be equal to '/'.
|
||||
It is set to '$NEXTCLOUD_DATADIR'."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [ -n "$NEXTCLOUD_MOUNT" ]; then
|
||||
if ! echo "$NEXTCLOUD_MOUNT" | grep -q "^/" || [ "$NEXTCLOUD_MOUNT" = "/" ]; then
|
||||
echo "You've set NEXCLOUD_MOUNT but not to an allowed value.
|
||||
The string must start with '/' and must not be equal to '/'.
|
||||
It is set to '$NEXTCLOUD_MOUNT'."
|
||||
exit 1
|
||||
elif [ "$NEXTCLOUD_MOUNT" = "/mnt/ncdata" ] || echo "$NEXTCLOUD_MOUNT" | grep -q "^/mnt/ncdata/"; then
|
||||
echo "'/mnt/ncdata' and '/mnt/ncdata/' are not allowed as values for NEXTCLOUD_MOUNT."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [ -n "$NEXTCLOUD_DATADIR" ] && [ -n "$NEXTCLOUD_MOUNT" ]; then
|
||||
if [ "$NEXTCLOUD_DATADIR" = "$NEXTCLOUD_MOUNT" ]; then
|
||||
echo "NEXTCLOUD_DATADIR and NEXTCLOUD_MOUNT are not allowed to be equal."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [ -n "$APACHE_PORT" ]; then
|
||||
if ! check_if_number "$APACHE_PORT"; then
|
||||
echo "You provided an Apache port but did not only use numbers.
|
||||
It is set to '$APACHE_PORT'."
|
||||
exit 1
|
||||
elif ! [ "$APACHE_PORT" -le 65535 ] || ! [ "$APACHE_PORT" -ge 1 ]; then
|
||||
echo "The provided Apache port is invalid. It must be between 1 and 65535"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [ -n "$APACHE_IP_BINDING" ]; then
|
||||
if ! echo "$APACHE_IP_BINDING" | grep -q '^[0-9.]\+$'; then
|
||||
echo "You provided an ip-address for the apache container's ip-binding but it was not a valid ip-address.
|
||||
It is set to '$APACHE_IP_BINDING'."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [ -n "$TALK_PORT" ]; then
|
||||
if ! check_if_number "$TALK_PORT"; then
|
||||
echo "You provided an Talk port but did not only use numbers.
|
||||
It is set to '$TALK_PORT'."
|
||||
exit 1
|
||||
elif ! [ "$TALK_PORT" -le 65535 ] || ! [ "$TALK_PORT" -ge 1 ]; then
|
||||
echo "The provided Talk port is invalid. It must be between 1 and 65535"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [ -n "$APACHE_PORT" ] && [ -n "$TALK_PORT" ]; then
|
||||
if [ "$APACHE_PORT" = "$TALK_PORT" ]; then
|
||||
echo "APACHE_PORT and TALK_PORT are not allowed to be equal."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [ -n "$DOCKER_SOCKET_PATH" ]; then
|
||||
if ! echo "$DOCKER_SOCKET_PATH" | grep -q "^/" || echo "$DOCKER_SOCKET_PATH" | grep -q "/$"; then
|
||||
echo "You've set DOCKER_SOCKET_PATH but not to an allowed value.
|
||||
The string must start with '/' and must not end with '/'.
|
||||
It is set to '$DOCKER_SOCKET_PATH'."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check DNS resolution
|
||||
# Prevents issues like https://github.com/nextcloud/all-in-one/discussions/565
|
||||
curl https://nextcloud.com &>/dev/null
|
||||
if [ "$?" = 6 ]; then
|
||||
echo "Could not resolve the host nextcloud.com."
|
||||
echo "Most likely the DNS resolving does not work."
|
||||
echo "You should be able to fix this by adding the '--dns=\"ip.address.of.dns.server\"' option to the docker run command."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Add important folders
|
||||
mkdir -p /mnt/docker-aio-config/data/
|
||||
mkdir -p /mnt/docker-aio-config/session/
|
||||
@@ -64,19 +167,33 @@ chmod 770 -R /mnt/docker-aio-config
|
||||
chmod 777 /mnt/docker-aio-config
|
||||
chown www-data:www-data -R /mnt/docker-aio-config/data/
|
||||
chown www-data:www-data -R /mnt/docker-aio-config/session/
|
||||
chown root:root -R /mnt/docker-aio-config/caddy/
|
||||
chown www-data:www-data -R /mnt/docker-aio-config/caddy/
|
||||
chown root:root -R /mnt/docker-aio-config/certs/
|
||||
|
||||
# Don't allow access to the AIO interface from the Nextcloud container
|
||||
# Probably more cosmetic than anything but at least an attempt
|
||||
if ! grep -q '# nextcloud-aio-block' /etc/apache2/apache2.conf; then
|
||||
cat << APACHE_CONF >> /etc/apache2/apache2.conf
|
||||
# nextcloud-aio-block-start
|
||||
<Location />
|
||||
order allow,deny
|
||||
deny from nextcloud-aio-nextcloud.nextcloud-aio
|
||||
allow from all
|
||||
</Location>
|
||||
# nextcloud-aio-block-end
|
||||
APACHE_CONF
|
||||
fi
|
||||
|
||||
# Adjust certs
|
||||
GENERATED_CERTS="/mnt/docker-aio-config/certs"
|
||||
TMP_CERTS="/etc/apache2/certs"
|
||||
mkdir -p "$GENERATED_CERTS"
|
||||
cd "$GENERATED_CERTS"
|
||||
cd "$GENERATED_CERTS" || exit 1
|
||||
if ! [ -f ./ssl.crt ] && ! [ -f ./ssl.key ]; then
|
||||
openssl req -new -newkey rsa:4096 -days 3650 -nodes -x509 -subj "/C=DE/ST=BE/L=Local/O=Dev/CN=nextcloud.local" -keyout ./ssl.key -out ./ssl.crt
|
||||
fi
|
||||
if [ -f ./ssl.crt ] && [ -f ./ssl.key ]; then
|
||||
cd "$TMP_CERTS"
|
||||
cd "$TMP_CERTS" || exit 1
|
||||
rm ./ssl.crt
|
||||
rm ./ssl.key
|
||||
cp "$GENERATED_CERTS/ssl.crt" ./
|
||||
@@ -90,4 +207,7 @@ E.g. https://internal.ip.of.this.server:8080
|
||||
If your server has port 80 and 8443 open and you point a domain to your server, you can get a valid certificate automatially by opening the Nextcloud AIO Interface via:
|
||||
https://your-domain-that-points-to-this-server.tld:8443"
|
||||
|
||||
# Set the timezone to UTC
|
||||
export TZ=UTC
|
||||
|
||||
exec "$@"
|
||||
|
||||
@@ -20,7 +20,7 @@ stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
command=/usr/bin/caddy run -config /Caddyfile
|
||||
command=sudo -u www-data /usr/bin/caddy run -config /Caddyfile
|
||||
|
||||
[program:cron]
|
||||
stdout_logfile=/dev/stdout
|
||||
@@ -28,3 +28,17 @@ stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
command=/cron.sh
|
||||
|
||||
[program:backup-time-file-watcher]
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
command=/backup-time-file-watcher.sh
|
||||
|
||||
[program:session-deduplicator]
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
command=/session-deduplicator.sh
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
# From https://github.com/nextcloud/docker/blob/master/22/fpm/Dockerfile
|
||||
FROM php:8.0-fpm-bullseye
|
||||
# From https://github.com/nextcloud/docker/blob/master/23/fpm-alpine/Dockerfile
|
||||
FROM php:8.0.21-fpm-alpine3.15
|
||||
|
||||
# Custom: change id of www-data user as it needs to be the same like on old installations
|
||||
RUN set -ex; \
|
||||
apk add --no-cache shadow; \
|
||||
deluser www-data; \
|
||||
groupmod -g 333 xfs; \
|
||||
usermod -u 333 -g 333 xfs; \
|
||||
addgroup -g 33 -S www-data; \
|
||||
adduser -u 33 -D -S -G www-data www-data
|
||||
|
||||
# entrypoint.sh and cron.sh dependencies
|
||||
RUN set -ex; \
|
||||
\
|
||||
apt-get update; \
|
||||
apt-get install -y --no-install-recommends \
|
||||
apk add --no-cache \
|
||||
rsync \
|
||||
bzip2 \
|
||||
; \
|
||||
rm -rf /var/lib/apt/lists/*;
|
||||
;
|
||||
|
||||
# install the PHP extensions we need
|
||||
# see https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html
|
||||
@@ -17,30 +23,28 @@ ENV PHP_MEMORY_LIMIT 512M
|
||||
ENV PHP_UPLOAD_LIMIT 10G
|
||||
RUN set -ex; \
|
||||
\
|
||||
savedAptMark="$(apt-mark showmanual)"; \
|
||||
\
|
||||
apt-get update; \
|
||||
apt-get install -y --no-install-recommends \
|
||||
libcurl4-openssl-dev \
|
||||
apk add --no-cache --virtual .build-deps \
|
||||
$PHPIZE_DEPS \
|
||||
autoconf \
|
||||
freetype-dev \
|
||||
icu-dev \
|
||||
libevent-dev \
|
||||
libfreetype6-dev \
|
||||
libicu-dev \
|
||||
libjpeg-dev \
|
||||
libldap2-dev \
|
||||
libjpeg-turbo-dev \
|
||||
libmcrypt-dev \
|
||||
libmemcached-dev \
|
||||
libpng-dev \
|
||||
libpq-dev \
|
||||
libmemcached-dev \
|
||||
libxml2-dev \
|
||||
libmagickwand-dev \
|
||||
libzip-dev \
|
||||
openldap-dev \
|
||||
pcre-dev \
|
||||
postgresql-dev \
|
||||
imagemagick-dev \
|
||||
libwebp-dev \
|
||||
libgmp-dev \
|
||||
gmp-dev \
|
||||
; \
|
||||
\
|
||||
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
|
||||
docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp; \
|
||||
docker-php-ext-configure ldap --with-libdir="lib/$debMultiarch"; \
|
||||
docker-php-ext-configure ldap; \
|
||||
docker-php-ext-install -j "$(nproc)" \
|
||||
bcmath \
|
||||
exif \
|
||||
@@ -57,8 +61,8 @@ RUN set -ex; \
|
||||
\
|
||||
# pecl will claim success even if one install fails, so we need to perform each install separately
|
||||
pecl install APCu-5.1.21; \
|
||||
pecl install memcached-3.1.5; \
|
||||
pecl install redis-5.3.6; \
|
||||
pecl install memcached-3.2.0; \
|
||||
pecl install redis-5.3.7; \
|
||||
pecl install imagick-3.7.0; \
|
||||
\
|
||||
docker-php-ext-enable \
|
||||
@@ -69,29 +73,21 @@ RUN set -ex; \
|
||||
; \
|
||||
rm -r /tmp/pear; \
|
||||
\
|
||||
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
|
||||
apt-mark auto '.*' > /dev/null; \
|
||||
apt-mark manual $savedAptMark; \
|
||||
ldd "$(php -r 'echo ini_get("extension_dir");')"/*.so \
|
||||
| awk '/=>/ { print $3 }' \
|
||||
| sort -u \
|
||||
| xargs -r dpkg-query -S \
|
||||
| cut -d: -f1 \
|
||||
| sort -u \
|
||||
| xargs -rt apt-mark manual; \
|
||||
\
|
||||
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
runDeps="$( \
|
||||
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/php/extensions \
|
||||
| tr ',' '\n' \
|
||||
| sort -u \
|
||||
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
|
||||
)"; \
|
||||
apk add --virtual .nextcloud-phpext-rundeps $runDeps; \
|
||||
apk del .build-deps
|
||||
|
||||
# set recommended PHP.ini settings
|
||||
# see https://docs.nextcloud.com/server/stable/admin_manual/configuration_server/server_tuning.html#enable-php-opcache
|
||||
RUN { \
|
||||
echo 'opcache.enable=1'; \
|
||||
echo 'opcache.interned_strings_buffer=8'; \
|
||||
echo 'opcache.max_accelerated_files=10000'; \
|
||||
echo 'opcache.memory_consumption=128'; \
|
||||
echo 'opcache.interned_strings_buffer=32'; \
|
||||
echo 'opcache.save_comments=1'; \
|
||||
echo 'opcache.revalidate_freq=1'; \
|
||||
echo 'opcache.revalidate_freq=60'; \
|
||||
} > /usr/local/etc/php/conf.d/opcache-recommended.ini; \
|
||||
\
|
||||
echo 'apc.enable_cli=1' >> /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini; \
|
||||
@@ -109,15 +105,13 @@ RUN { \
|
||||
VOLUME /var/www/html
|
||||
|
||||
|
||||
ENV NEXTCLOUD_VERSION 23.0.0
|
||||
ENV NEXTCLOUD_VERSION 23.0.6
|
||||
|
||||
RUN set -ex; \
|
||||
fetchDeps=" \
|
||||
apk add --no-cache --virtual .fetch-deps \
|
||||
bzip2 \
|
||||
gnupg \
|
||||
dirmngr \
|
||||
"; \
|
||||
apt-get update; \
|
||||
apt-get install -y --no-install-recommends $fetchDeps; \
|
||||
; \
|
||||
\
|
||||
curl -fsSL -o nextcloud.tar.bz2 \
|
||||
"https://download.nextcloud.com/server/releases/nextcloud-${NEXTCLOUD_VERSION}.tar.bz2"; \
|
||||
@@ -125,7 +119,7 @@ RUN set -ex; \
|
||||
"https://download.nextcloud.com/server/releases/nextcloud-${NEXTCLOUD_VERSION}.tar.bz2.asc"; \
|
||||
export GNUPGHOME="$(mktemp -d)"; \
|
||||
# gpg key from https://nextcloud.com/nextcloud.asc
|
||||
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys 28806A878AE423A28372792ED75899B9A724937A; \
|
||||
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys 28806A878AE423A28372792ED75899B9A724937A; \
|
||||
gpg --batch --verify nextcloud.tar.bz2.asc nextcloud.tar.bz2; \
|
||||
tar -xjf nextcloud.tar.bz2 -C /usr/src/; \
|
||||
gpgconf --kill all; \
|
||||
@@ -134,9 +128,7 @@ RUN set -ex; \
|
||||
mkdir -p /usr/src/nextcloud/data; \
|
||||
mkdir -p /usr/src/nextcloud/custom_apps; \
|
||||
chmod +x /usr/src/nextcloud/occ; \
|
||||
\
|
||||
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false $fetchDeps; \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
apk del .fetch-deps
|
||||
|
||||
COPY *.sh upgrade.exclude /
|
||||
COPY config/* /usr/src/nextcloud/config/
|
||||
@@ -144,31 +136,28 @@ COPY config/* /usr/src/nextcloud/config/
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
CMD ["php-fpm"]
|
||||
|
||||
# Template from https://github.com/nextcloud/docker/blob/master/.examples/dockerfiles/full/fpm/Dockerfile
|
||||
# Template from https://github.com/nextcloud/docker/blob/master/.examples/dockerfiles/full/fpm-alpine/Dockerfile
|
||||
|
||||
RUN set -ex; \
|
||||
\
|
||||
apt-get update; \
|
||||
apt-get install -y --no-install-recommends \
|
||||
apk add --no-cache \
|
||||
ffmpeg \
|
||||
libmagickcore-6.q16-6-extra \
|
||||
imagemagick \
|
||||
procps \
|
||||
smbclient \
|
||||
samba-client \
|
||||
supervisor \
|
||||
# libreoffice \
|
||||
; \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
;
|
||||
|
||||
RUN set -ex; \
|
||||
\
|
||||
savedAptMark="$(apt-mark showmanual)"; \
|
||||
\
|
||||
apt-get update; \
|
||||
apt-get install -y --no-install-recommends \
|
||||
libbz2-dev \
|
||||
libc-client-dev \
|
||||
libkrb5-dev \
|
||||
libsmbclient-dev \
|
||||
apk add --no-cache --virtual .build-deps \
|
||||
$PHPIZE_DEPS \
|
||||
imap-dev \
|
||||
krb5-dev \
|
||||
openssl-dev \
|
||||
samba-dev \
|
||||
bzip2-dev \
|
||||
; \
|
||||
\
|
||||
docker-php-ext-configure imap --with-kerberos --with-imap-ssl; \
|
||||
@@ -179,19 +168,14 @@ RUN set -ex; \
|
||||
pecl install smbclient; \
|
||||
docker-php-ext-enable smbclient; \
|
||||
\
|
||||
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
|
||||
apt-mark auto '.*' > /dev/null; \
|
||||
apt-mark manual $savedAptMark; \
|
||||
ldd "$(php -r 'echo ini_get("extension_dir");')"/*.so \
|
||||
| awk '/=>/ { print $3 }' \
|
||||
| sort -u \
|
||||
| xargs -r dpkg-query -S \
|
||||
| cut -d: -f1 \
|
||||
| sort -u \
|
||||
| xargs -rt apt-mark manual; \
|
||||
\
|
||||
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
runDeps="$( \
|
||||
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/php/extensions \
|
||||
| tr ',' '\n' \
|
||||
| sort -u \
|
||||
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
|
||||
)"; \
|
||||
apk add --virtual .nextcloud-phpext-rundeps $runDeps; \
|
||||
apk del .build-deps
|
||||
|
||||
RUN mkdir -p \
|
||||
/var/log/supervisord \
|
||||
@@ -207,14 +191,14 @@ CMD ["/usr/bin/supervisord", "-c", "/supervisord.conf"]
|
||||
# Custom:
|
||||
RUN set -ex; \
|
||||
\
|
||||
apt-get update; \
|
||||
apt-get install -y --no-install-recommends \
|
||||
netcat \
|
||||
apk add --no-cache \
|
||||
bash \
|
||||
netcat-openbsd \
|
||||
openssl \
|
||||
gnupg \
|
||||
dirmngr \
|
||||
git \
|
||||
postgresql-client \
|
||||
tzdata \
|
||||
; \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
@@ -225,31 +209,34 @@ RUN set -ex; \
|
||||
sed -i 's/^pm.min_spare_servers =.*/pm.min_spare_servers = 25/' /usr/local/etc/php-fpm.d/www.conf; \
|
||||
sed -i 's/^pm.max_spare_servers =.*/pm.max_spare_servers = 75/' /usr/local/etc/php-fpm.d/www.conf
|
||||
|
||||
RUN rm -rf /tmp/nextcloud-aio && \
|
||||
RUN set -ex; \
|
||||
rm -rf /tmp/nextcloud-aio && \
|
||||
mkdir -p /tmp/nextcloud-aio && \
|
||||
cd /tmp/nextcloud-aio && \
|
||||
git clone https://github.com/nextcloud/all-in-one.git .; \
|
||||
git clone https://github.com/nextcloud-releases/all-in-one.git --depth 1 .; \
|
||||
mkdir -p /usr/src/nextcloud/apps/nextcloud-aio; \
|
||||
cp -r ./app/* /usr/src/nextcloud/apps/nextcloud-aio/
|
||||
|
||||
RUN chown www-data:root -R /usr/src && \
|
||||
RUN set -ex; \
|
||||
chown www-data:root -R /usr/src && \
|
||||
chown www-data:root -R /usr/local/etc/php/conf.d && \
|
||||
chown www-data:root -R /var/log/supervisord/ && \
|
||||
chown www-data:root -R /var/run/supervisord/ && \
|
||||
mkdir -p /var/log/nextcloud/ && \
|
||||
chown -R www-data:root /var/log/nextcloud/ && \
|
||||
rm -r /usr/src/nextcloud/apps/updatenotification
|
||||
|
||||
COPY start.sh /
|
||||
COPY notify.sh /
|
||||
RUN chmod +x /start.sh && \
|
||||
RUN set -ex; \
|
||||
chmod +x /start.sh && \
|
||||
chmod +r /supervisord.conf && \
|
||||
chmod +x /entrypoint.sh && \
|
||||
chmod +r /upgrade.exclude && \
|
||||
chmod +x /cron.sh && \
|
||||
chmod +x /notify.sh
|
||||
chmod +x /notify.sh && \
|
||||
chmod +x /activate-collabora.sh
|
||||
|
||||
RUN mkdir /mnt/ncdata; \
|
||||
RUN set -ex; \
|
||||
mkdir /mnt/ncdata; \
|
||||
chown www-data:www-data /mnt/ncdata;
|
||||
|
||||
VOLUME /mnt/ncdata
|
||||
|
||||
20
Containers/nextcloud/activate-collabora.sh
Normal file
20
Containers/nextcloud/activate-collabora.sh
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
COLLABORA_ACTIVATED=0
|
||||
|
||||
while true; do
|
||||
if [ "$COLLABORA_ENABLED" != yes ]; then
|
||||
# Basically sleep for forever if collabora is not enabled
|
||||
sleep 365d
|
||||
fi
|
||||
if [ "$COLLABORA_ACTIVATED" != 0 ]; then
|
||||
# Basically sleep for forever if collabora was activated
|
||||
sleep 365d
|
||||
fi
|
||||
while ! nc -z "$NC_DOMAIN" 443; do
|
||||
sleep 5
|
||||
done
|
||||
echo "Activating collabora config"
|
||||
php /var/www/html/occ richdocuments:activate-config
|
||||
COLLABORA_ACTIVATED=1
|
||||
done
|
||||
@@ -18,8 +18,3 @@ $overwriteCondAddr = getenv('OVERWRITECONDADDR');
|
||||
if ($overwriteCondAddr) {
|
||||
$CONFIG['overwritecondaddr'] = $overwriteCondAddr;
|
||||
}
|
||||
|
||||
$trustedProxies = getenv('TRUSTED_PROXIES');
|
||||
if ($trustedProxies) {
|
||||
$CONFIG['trusted_proxies'] = array_filter(array_map('trim', explode(' ', $trustedProxies)));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
set -eu
|
||||
|
||||
while true; do
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
|
||||
# version_greater A B returns whether A > B
|
||||
version_greater() {
|
||||
@@ -21,6 +21,15 @@ redis.session.lock_retries = -1
|
||||
redis.session.lock_wait_time = 10000
|
||||
REDIS_CONF
|
||||
|
||||
# Check permissions in ncdata
|
||||
touch "/mnt/ncdata/this-is-a-test-file"
|
||||
if ! [ -f "/mnt/ncdata/this-is-a-test-file" ]; then
|
||||
echo "The www-data user doesn't seem to have access rights in /mnt/ncdata.
|
||||
Did you maybe change the datadir and did forget to apply the correct permissions?"
|
||||
exit 1
|
||||
fi
|
||||
rm "/mnt/ncdata/this-is-a-test-file"
|
||||
|
||||
if [ -f /var/www/html/version.php ]; then
|
||||
# shellcheck disable=SC2016
|
||||
installed_version="$(php -r 'require "/var/www/html/version.php"; echo implode(".", $OC_Version);')"
|
||||
@@ -39,6 +48,15 @@ if [ "$installed_version" != "0.0.0.0" ]; then
|
||||
unset ADMIN_PASSWORD
|
||||
fi
|
||||
|
||||
# Don't start the container if Nextcloud is not compatible with the PHP version
|
||||
if [ -f "/var/www/html/lib/versioncheck.php" ] && ! php /var/www/html/lib/versioncheck.php; then
|
||||
echo "It seems like your installed Nextcloud is not compatible with the by the container provided PHP version."
|
||||
echo "This most likely happened because you tried to restore an old Nextcloud version from backup that is not compatible with the PHP version that comes with the container."
|
||||
echo "Please try to restore a more recent backup which contains a Nextcloud version that is compatible with the PHP version that comes with the container."
|
||||
echo "If you do not have a more recent backup, feel free to have a look at this documentation: https://github.com/nextcloud/all-in-one/blob/main/manual-upgrade.md"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Skip any update if Nextcloud was just restored
|
||||
if ! [ -f "/mnt/ncdata/skip.update" ]; then
|
||||
if version_greater "$image_version" "$installed_version"; then
|
||||
@@ -50,7 +68,8 @@ if ! [ -f "/mnt/ncdata/skip.update" ]; then
|
||||
NEXT_MAJOR="$((INSTALLED_MAJOR + 1))"
|
||||
curl -fsSL -o nextcloud.tar.bz2 "https://download.nextcloud.com/server/releases/latest-${NEXT_MAJOR}.tar.bz2"
|
||||
curl -fsSL -o nextcloud.tar.bz2.asc "https://download.nextcloud.com/server/releases/latest-${NEXT_MAJOR}.tar.bz2.asc"
|
||||
export GNUPGHOME="$(mktemp -d)"
|
||||
GNUPGHOME="$(mktemp -d)"
|
||||
export GNUPGHOME
|
||||
# gpg key from https://nextcloud.com/nextcloud.asc
|
||||
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys 28806A878AE423A28372792ED75899B9A724937A
|
||||
gpg --batch --verify nextcloud.tar.bz2.asc nextcloud.tar.bz2
|
||||
@@ -63,6 +82,8 @@ if ! [ -f "/mnt/ncdata/skip.update" ]; then
|
||||
mkdir -p /usr/src/tmp/nextcloud/custom_apps
|
||||
chmod +x /usr/src/tmp/nextcloud/occ
|
||||
cp /usr/src/nextcloud/config/* /usr/src/tmp/nextcloud/config/
|
||||
mkdir -p /usr/src/tmp/nextcloud/apps/nextcloud-aio
|
||||
cp /usr/src/nextcloud/apps/nextcloud-aio/* /usr/src/tmp/nextcloud/apps/nextcloud-aio/
|
||||
mv /usr/src/nextcloud /usr/src/temp-nextcloud
|
||||
mv /usr/src/tmp/nextcloud /usr/src/nextcloud
|
||||
rm -r /usr/src/tmp
|
||||
@@ -97,6 +118,11 @@ if ! [ -f "/mnt/ncdata/skip.update" ]; then
|
||||
fi
|
||||
|
||||
php /var/www/html/occ app:update --all
|
||||
|
||||
# Fix removing the updatenotification for old instances
|
||||
if [ -d "/var/www/html/apps/updatenotification" ]; then
|
||||
php /var/www/html/occ app:disable updatenotification
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Initializing nextcloud $image_version ..."
|
||||
@@ -144,10 +170,10 @@ if ! [ -f "/mnt/ncdata/skip.update" ]; then
|
||||
mkdir -p /var/www/html/data
|
||||
php /var/www/html/occ config:system:set loglevel --value=2
|
||||
php /var/www/html/occ config:system:set log_type --value=file
|
||||
php /var/www/html/occ config:system:set logfile --value="/var/log/nextcloud/nextcloud.log"
|
||||
php /var/www/html/occ config:system:set logfile --value="/var/www/html/data/nextcloud.log"
|
||||
php /var/www/html/occ config:system:set log_rotate_size --value="10485760"
|
||||
php /var/www/html/occ app:enable admin_audit
|
||||
php /var/www/html/occ config:app:set admin_audit logfile --value="/var/log/nextcloud/audit.log"
|
||||
php /var/www/html/occ config:app:set admin_audit logfile --value="/var/www/html/data/audit.log"
|
||||
php /var/www/html/occ config:system:set log.condition apps 0 --value="admin_audit"
|
||||
|
||||
# Apply preview settings
|
||||
@@ -177,6 +203,14 @@ if ! [ -f "/mnt/ncdata/skip.update" ]; then
|
||||
# Not needed anymore with the removal of the updatenotification app:
|
||||
# php /var/www/html/occ config:app:set updatenotification notify_groups --value="[]"
|
||||
|
||||
# Install some apps by default
|
||||
php /var/www/html/occ app:install twofactor_totp
|
||||
php /var/www/html/occ app:install deck
|
||||
php /var/www/html/occ app:install tasks
|
||||
php /var/www/html/occ app:install calendar
|
||||
php /var/www/html/occ app:install contacts
|
||||
php /var/www/html/occ app:install apporder
|
||||
|
||||
#upgrade
|
||||
else
|
||||
while [ -n "$(pgrep -f cron.php)" ]
|
||||
@@ -188,9 +222,12 @@ if ! [ -f "/mnt/ncdata/skip.update" ]; then
|
||||
echo "Upgrading nextcloud from $installed_version to $image_version..."
|
||||
if ! php /var/www/html/occ upgrade || ! php /var/www/html/occ -V; then
|
||||
echo "Upgrade failed. Please restore from backup."
|
||||
bash /notify.sh "Nextcloud update to $image_version failed!" "Please restore from backup!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
bash /notify.sh "Nextcloud update to $image_version successful!" "Feel free to inspect the Nextcloud container logs for more info."
|
||||
|
||||
php /var/www/html/occ app:list | sed -n "/Enabled:/,/Disabled:/p" > /tmp/list_after
|
||||
echo "The following apps have been disabled:"
|
||||
diff /tmp/list_before /tmp/list_after | grep '<' | cut -d- -f2 | cut -d: -f1
|
||||
@@ -207,6 +244,27 @@ if ! [ -f "/mnt/ncdata/skip.update" ]; then
|
||||
php /var/www/html/occ maintenance:mimetype:update-db
|
||||
fi
|
||||
fi
|
||||
|
||||
# Performing update of all apps if daily backups are enabled, running and successful and if it is saturday
|
||||
if [ "$UPDATE_NEXTCLOUD_APPS" = 'yes' ] && [ "$(date +%u)" = 6 ]; then
|
||||
UPDATED_APPS="$(php /var/www/html/occ app:update --all)"
|
||||
if [ -n "$UPDATED_APPS" ]; then
|
||||
bash /notify.sh "Your apps just got updated!" "$UPDATED_APPS"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if appdata is present
|
||||
# If not, something broke (e.g. changing ncdatadir after aio was first started)
|
||||
if [ -z "$(find "/mnt/ncdata/" -maxdepth 1 -mindepth 1 -type d -name "appdata_*")" ]; then
|
||||
echo "Appdata is not present. Did you maybe change the datadir after aio was first started?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Perform fingerprint update if instance was restored
|
||||
if [ -f "/mnt/ncdata/fingerprint.update" ]; then
|
||||
php /var/www/html/occ maintenance:data-fingerprint
|
||||
rm "/mnt/ncdata/fingerprint.update"
|
||||
fi
|
||||
|
||||
# Apply one-click-instance settings
|
||||
@@ -214,6 +272,11 @@ echo "Applying one-click-instance settings..."
|
||||
php /var/www/html/occ config:system:set one-click-instance --value=true --type=bool
|
||||
php /var/www/html/occ config:system:set one-click-instance.user-limit --value=100 --type=int
|
||||
|
||||
# Adjusting log files to be stored on a volume
|
||||
echo "Adjusting log files..."
|
||||
php /var/www/html/occ config:system:set logfile --value="/var/www/html/data/nextcloud.log"
|
||||
php /var/www/html/occ config:app:set admin_audit logfile --value="/var/www/html/data/audit.log"
|
||||
|
||||
# Apply network settings
|
||||
echo "Applying network settings..."
|
||||
php /var/www/html/occ config:system:set trusted_domains 1 --value="$NC_DOMAIN"
|
||||
@@ -221,6 +284,13 @@ php /var/www/html/occ config:system:set overwrite.cli.url --value="https://$NC_D
|
||||
php /var/www/html/occ config:system:set htaccess.RewriteBase --value="/"
|
||||
php /var/www/html/occ maintenance:update:htaccess
|
||||
|
||||
# Disallow creating local external storages when nothing was mounted
|
||||
if [ -z "$NEXTCLOUD_MOUNT" ]; then
|
||||
php /var/www/html/occ config:system:set files_external_allow_create_new_local --type=bool --value=false
|
||||
else
|
||||
php /var/www/html/occ config:system:set files_external_allow_create_new_local --type=bool --value=true
|
||||
fi
|
||||
|
||||
# AIO app
|
||||
if [ "$(php /var/www/html/occ config:app:get nextcloud-aio enabled)" = "" ]; then
|
||||
php /var/www/html/occ app:enable nextcloud-aio
|
||||
@@ -236,33 +306,96 @@ elif [ "$(php /var/www/html/occ config:app:get notify_push enabled)" = "no" ]; t
|
||||
else
|
||||
php /var/www/html/occ app:update notify_push
|
||||
fi
|
||||
php /var/www/html/occ config:system:set trusted_proxies 0 --value="127.0.0.1"
|
||||
php /var/www/html/occ config:system:set trusted_proxies 1 --value="::1"
|
||||
php /var/www/html/occ config:app:set notify_push base_endpoint --value="https://$NC_DOMAIN/push"
|
||||
|
||||
# Collabora
|
||||
if ! [ -d "/var/www/html/custom_apps/richdocuments" ]; then
|
||||
php /var/www/html/occ app:install richdocuments
|
||||
elif [ "$(php /var/www/html/occ config:app:get richdocuments enabled)" = "no" ]; then
|
||||
php /var/www/html/occ app:enable richdocuments
|
||||
if [ "$COLLABORA_ENABLED" = 'yes' ]; then
|
||||
if ! [ -d "/var/www/html/custom_apps/richdocuments" ]; then
|
||||
php /var/www/html/occ app:install richdocuments
|
||||
elif [ "$(php /var/www/html/occ config:app:get richdocuments enabled)" = "no" ]; then
|
||||
php /var/www/html/occ app:enable richdocuments
|
||||
else
|
||||
php /var/www/html/occ app:update richdocuments
|
||||
fi
|
||||
php /var/www/html/occ config:app:set richdocuments wopi_url --value="https://$NC_DOMAIN/"
|
||||
# Fix https://github.com/nextcloud/all-in-one/issues/188:
|
||||
php /var/www/html/occ config:system:set allow_local_remote_servers --type=bool --value=true
|
||||
else
|
||||
php /var/www/html/occ app:update richdocuments
|
||||
if [ -d "/var/www/html/custom_apps/richdocuments" ]; then
|
||||
php /var/www/html/occ app:remove richdocuments
|
||||
fi
|
||||
fi
|
||||
|
||||
# OnlyOffice
|
||||
if [ "$ONLYOFFICE_ENABLED" = 'yes' ]; then
|
||||
while ! nc -z "$ONLYOFFICE_HOST" 80; do
|
||||
echo "waiting for OnlyOffice to become available..."
|
||||
sleep 5
|
||||
done
|
||||
if ! [ -d "/var/www/html/custom_apps/onlyoffice" ]; then
|
||||
php /var/www/html/occ app:install onlyoffice
|
||||
elif [ "$(php /var/www/html/occ config:app:get onlyoffice enabled)" = "no" ]; then
|
||||
php /var/www/html/occ app:enable onlyoffice
|
||||
else
|
||||
php /var/www/html/occ app:update onlyoffice
|
||||
fi
|
||||
php /var/www/html/occ config:system:set onlyoffice jwt_secret --value="$ONLYOFFICE_SECRET"
|
||||
php /var/www/html/occ config:system:set onlyoffice jwt_header --value="AuthorizationJwt"
|
||||
php /var/www/html/occ config:app:set onlyoffice DocumentServerUrl --value="https://$NC_DOMAIN/onlyoffice"
|
||||
php /var/www/html/occ config:system:set allow_local_remote_servers --type=bool --value=true
|
||||
else
|
||||
if [ -d "/var/www/html/custom_apps/onlyoffice" ]; then
|
||||
php /var/www/html/occ app:remove onlyoffice
|
||||
fi
|
||||
fi
|
||||
php /var/www/html/occ config:app:set richdocuments wopi_url --value="https://$NC_DOMAIN/"
|
||||
# php /var/www/html/occ richdocuments:activate-config
|
||||
|
||||
# Talk
|
||||
if ! [ -d "/var/www/html/custom_apps/spreed" ]; then
|
||||
php /var/www/html/occ app:install spreed
|
||||
elif [ "$(php /var/www/html/occ config:app:get spreed enabled)" = "no" ]; then
|
||||
php /var/www/html/occ app:enable spreed
|
||||
if [ "$TALK_ENABLED" = 'yes' ]; then
|
||||
if ! [ -d "/var/www/html/custom_apps/spreed" ]; then
|
||||
php /var/www/html/occ app:install spreed
|
||||
elif [ "$(php /var/www/html/occ config:app:get spreed enabled)" = "no" ]; then
|
||||
php /var/www/html/occ app:enable spreed
|
||||
else
|
||||
php /var/www/html/occ app:update spreed
|
||||
fi
|
||||
STUN_SERVERS="[\"$NC_DOMAIN:$TALK_PORT\"]"
|
||||
TURN_SERVERS="[{\"server\":\"$NC_DOMAIN:$TALK_PORT\",\"secret\":\"$TURN_SECRET\",\"protocols\":\"udp,tcp\"}]"
|
||||
SIGNALING_SERVERS="{\"servers\":[{\"server\":\"https://$NC_DOMAIN/standalone-signaling/\",\"verify\":true}],\"secret\":\"$SIGNALING_SECRET\"}"
|
||||
php /var/www/html/occ config:app:set spreed stun_servers --value="$STUN_SERVERS" --output json
|
||||
php /var/www/html/occ config:app:set spreed turn_servers --value="$TURN_SERVERS" --output json
|
||||
php /var/www/html/occ config:app:set spreed signaling_servers --value="$SIGNALING_SERVERS" --output json
|
||||
else
|
||||
php /var/www/html/occ app:update spreed
|
||||
if [ -d "/var/www/html/custom_apps/spreed" ]; then
|
||||
php /var/www/html/occ app:remove spreed
|
||||
fi
|
||||
fi
|
||||
|
||||
# Clamav
|
||||
if [ "$CLAMAV_ENABLED" = 'yes' ]; then
|
||||
while ! nc -z "$CLAMAV_HOST" 3310; do
|
||||
echo "waiting for clamav to become available..."
|
||||
sleep 5
|
||||
done
|
||||
if ! [ -d "/var/www/html/custom_apps/files_antivirus" ]; then
|
||||
php /var/www/html/occ app:install files_antivirus
|
||||
elif [ "$(php /var/www/html/occ config:app:get files_antivirus enabled)" = "no" ]; then
|
||||
php /var/www/html/occ app:enable files_antivirus
|
||||
else
|
||||
php /var/www/html/occ app:update files_antivirus
|
||||
fi
|
||||
php /var/www/html/occ config:app:set files_antivirus av_mode --value="daemon"
|
||||
php /var/www/html/occ config:app:set files_antivirus av_port --value="3310"
|
||||
php /var/www/html/occ config:app:set files_antivirus av_host --value="$CLAMAV_HOST"
|
||||
php /var/www/html/occ config:app:set files_antivirus av_stream_max_length --value="104857600"
|
||||
php /var/www/html/occ config:app:set files_antivirus av_max_file_size --value="-1"
|
||||
php /var/www/html/occ config:app:set files_antivirus av_infected_action --value="only_log"
|
||||
else
|
||||
if [ -d "/var/www/html/custom_apps/files_antivirus" ]; then
|
||||
php /var/www/html/occ app:remove files_antivirus
|
||||
fi
|
||||
fi
|
||||
STUN_SERVERS="[\"$NC_DOMAIN:3478\"]"
|
||||
TURN_SERVERS="[{\"server\":\"$NC_DOMAIN:3478\",\"secret\":\"$TURN_SECRET\",\"protocols\":\"udp,tcp\"}]"
|
||||
SIGNALING_SERVERS="{\"servers\":[{\"server\":\"https://$NC_DOMAIN/standalone-signaling/\",\"verify\":true}],\"secret\":\"$SIGNALING_SECRET\"}"
|
||||
php /var/www/html/occ config:app:set spreed stun_servers --value="$STUN_SERVERS" --output json
|
||||
php /var/www/html/occ config:app:set spreed turn_servers --value="$TURN_SERVERS" --output json
|
||||
php /var/www/html/occ config:app:set spreed signaling_servers --value="$SIGNALING_SERVERS" --output json
|
||||
|
||||
# Remove the update skip file always
|
||||
rm -f /mnt/ncdata/skip.update
|
||||
|
||||
@@ -6,13 +6,24 @@ while ! nc -z "$POSTGRES_HOST" 5432; do
|
||||
sleep 5
|
||||
done
|
||||
|
||||
# Use the correct Postgres username
|
||||
POSTGRES_USER="oc_$POSTGRES_USER"
|
||||
export POSTGRES_USER
|
||||
|
||||
# Fix false database connection on old instances
|
||||
if [ -f "/var/www/html/config/config.php" ] && sleep 2 && psql -d "postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:5432/$POSTGRES_DB" -c "select now()"; then
|
||||
sed -i "s|'dbuser'.*=>.*$|'dbuser' => '$POSTGRES_USER',|" /var/www/html/config/config.php
|
||||
sed -i "s|'dbpassword'.*=>.*$|'dbpassword' => '$POSTGRES_PASSWORD',|" /var/www/html/config/config.php
|
||||
fi
|
||||
|
||||
# Run original entrypoint
|
||||
if ! bash /entrypoint.sh; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Correctly set CPU_ARCH for notify_push
|
||||
export CPU_ARCH="$(uname -m)"
|
||||
CPU_ARCH="$(uname -m)"
|
||||
export CPU_ARCH
|
||||
if [ -z "$CPU_ARCH" ]; then
|
||||
echo "Could not get processor architecture. Exiting."
|
||||
exit 1
|
||||
|
||||
@@ -28,3 +28,10 @@ stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
command=/var/www/html/custom_apps/notify_push/bin/%(ENV_CPU_ARCH)s/notify_push /var/www/html/config/config.php --port 7867 --redis-url redis://:%(ENV_REDIS_HOST_PASSWORD)s@%(ENV_REDIS_HOST)s
|
||||
|
||||
[program:activate-collabora]
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
command=/activate-collabora.sh
|
||||
|
||||
2
Containers/onlyoffice/Dockerfile
Normal file
2
Containers/onlyoffice/Dockerfile
Normal file
@@ -0,0 +1,2 @@
|
||||
# From https://github.com/ONLYOFFICE/Docker-DocumentServer/blob/master/Dockerfile
|
||||
FROM onlyoffice/documentserver:7.1.1.23
|
||||
@@ -1,16 +1,25 @@
|
||||
# From https://github.com/docker-library/postgres/blob/master/13/bullseye/Dockerfile
|
||||
FROM postgres:13-bullseye
|
||||
# From https://github.com/docker-library/postgres/blob/master/13/alpine/Dockerfile
|
||||
FROM postgres:14.4-alpine
|
||||
|
||||
RUN apk add --update --no-cache bash openssl shadow netcat-openbsd
|
||||
|
||||
# We need to use the same gid and uid as on old installations
|
||||
RUN set -ex; \
|
||||
\
|
||||
apt-get update; \
|
||||
apt-get install -y --no-install-recommends \
|
||||
openssl \
|
||||
; \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
deluser postgres; \
|
||||
groupmod -g 9999 ping; \
|
||||
addgroup -g 999 -S postgres; \
|
||||
adduser -u 999 -S -D -G postgres -H -h /var/lib/postgresql -s /bin/sh postgres
|
||||
|
||||
# Fix default permissions
|
||||
RUN set -ex; \
|
||||
chown -R postgres:postgres /var/lib/postgresql; \
|
||||
chown -R postgres:postgres /var/run/postgresql; \
|
||||
chown -R postgres:postgres "$PGDATA"
|
||||
|
||||
COPY start.sh /usr/bin/
|
||||
RUN chmod +x /usr/bin/start.sh
|
||||
COPY init-user-db.sh /docker-entrypoint-initdb.d/
|
||||
RUN chmod +x /usr/bin/start.sh; \
|
||||
chmod +xr /docker-entrypoint-initdb.d/init-user-db.sh
|
||||
|
||||
RUN mkdir /mnt/data; \
|
||||
chown postgres:postgres /mnt/data;
|
||||
|
||||
9
Containers/postgresql/init-user-db.sh
Normal file
9
Containers/postgresql/init-user-db.sh
Normal file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
||||
CREATE USER "oc_$POSTGRES_USER" WITH PASSWORD '$POSTGRES_PASSWORD' CREATEDB;
|
||||
ALTER DATABASE "$POSTGRES_DB" OWNER TO "oc_$POSTGRES_USER";
|
||||
EOSQL
|
||||
|
||||
set +ex
|
||||
@@ -18,9 +18,18 @@ if ! [ -w "$DUMP_DIR" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Delete the datadir once (needed for setting the correct credentials on old instances once)
|
||||
if ! [ -f "$DUMP_DIR/export.failed" ] && ! [ -f "$DUMP_DIR/initial-cleanup-done" ]; then
|
||||
set -ex
|
||||
rm -rf "${DATADIR:?}/"*
|
||||
touch "$DUMP_DIR/initial-cleanup-done"
|
||||
set +ex
|
||||
fi
|
||||
|
||||
# Test if some things match
|
||||
# shellcheck disable=SC2235
|
||||
if ( [ -f "$DATADIR/PG_VERSION" ] && [ "$PG_MAJOR" != "$(cat "$DATADIR/PG_VERSION")" ] ) \
|
||||
|| ( ! [ -f "$DATADIR/PG_VERSION" ] && [ -f "$DUMP_FILE" ] ); then
|
||||
|| ( ! [ -f "$DATADIR/PG_VERSION" ] && ( [ -f "$DUMP_FILE" ] || [ -f "$DUMP_DIR/export.failed" ] ) ); then
|
||||
# The DUMP_file must be provided
|
||||
if ! [ -f "$DUMP_FILE" ]; then
|
||||
echo "Unable to restore the database because the database dump is missing."
|
||||
@@ -38,10 +47,10 @@ if ( [ -f "$DATADIR/PG_VERSION" ] && [ "$PG_MAJOR" != "$(cat "$DATADIR/PG_VERSIO
|
||||
echo "Restoring from database dump."
|
||||
|
||||
# Exit if any command fails
|
||||
set -e
|
||||
set -ex
|
||||
|
||||
# Remove old database files
|
||||
rm -rf "$DATADIR/"*
|
||||
rm -rf "${DATADIR:?}/"*
|
||||
|
||||
# Change database port to a random port temporarily
|
||||
export PGPORT=11000
|
||||
@@ -49,13 +58,33 @@ if ( [ -f "$DATADIR/PG_VERSION" ] && [ "$PG_MAJOR" != "$(cat "$DATADIR/PG_VERSIO
|
||||
# Create new database
|
||||
exec docker-entrypoint.sh postgres &
|
||||
|
||||
# Wait 2s for creation
|
||||
sleep 2s
|
||||
# Wait for creation
|
||||
while ! nc -z localhost 11000; do
|
||||
echo "Waiting for the database to start."
|
||||
sleep 5
|
||||
done
|
||||
|
||||
# Set correct permissions
|
||||
if grep -q "Owner: oc_admin" "$DUMP_FILE" && ! grep -q "Owner: oc_$POSTGRES_USER" "$DUMP_FILE"; then
|
||||
OC_ADMIN_EXISTS=1
|
||||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
||||
CREATE USER oc_admin WITH PASSWORD '$POSTGRES_PASSWORD' CREATEDB;
|
||||
ALTER DATABASE "$POSTGRES_DB" OWNER TO oc_admin;
|
||||
EOSQL
|
||||
fi
|
||||
|
||||
# Restore database
|
||||
echo "Restoring the database from database dump"
|
||||
psql "$POSTGRES_DB" -U "$POSTGRES_USER" < "$DUMP_FILE"
|
||||
|
||||
# Correct permissions
|
||||
if [ -n "$OC_ADMIN_EXISTS" ]; then
|
||||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
||||
ALTER DATABASE "$POSTGRES_DB" OWNER TO "oc_$POSTGRES_USER";
|
||||
REASSIGN OWNED BY oc_admin TO "oc_$POSTGRES_USER";
|
||||
EOSQL
|
||||
fi
|
||||
|
||||
# Shut down the database to be able to start it again
|
||||
pg_ctl stop -m fast
|
||||
|
||||
@@ -63,13 +92,13 @@ if ( [ -f "$DATADIR/PG_VERSION" ] && [ "$PG_MAJOR" != "$(cat "$DATADIR/PG_VERSIO
|
||||
export PGPORT=5432
|
||||
|
||||
# Don't exit if command fails anymore
|
||||
set +e
|
||||
set +ex
|
||||
fi
|
||||
|
||||
# Cover the last case
|
||||
if ! [ -f "$DATADIR/PG_VERSION" ] && ! [ -f "$DUMP_FILE" ]; then
|
||||
# Remove old database files if somehow there should be some
|
||||
rm -rf "$DATADIR/"*
|
||||
rm -rf "${DATADIR:?}/"*
|
||||
fi
|
||||
|
||||
# Catch docker stop attempts
|
||||
@@ -91,6 +120,6 @@ if pg_dump --username "$POSTGRES_USER" "$POSTGRES_DB" > "$DUMP_FILE.temp"; then
|
||||
exit 0
|
||||
else
|
||||
pg_ctl stop -m fast
|
||||
echo "Database dump unsucessful!"
|
||||
echo "Database dump unsuccessful!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
# From https://github.com/docker-library/redis/blob/master/6.2/Dockerfile
|
||||
FROM redis:6.2-bullseye
|
||||
# From https://github.com/docker-library/redis/blob/master/6.2/alpine/Dockerfile
|
||||
FROM redis:6.2.7-alpine
|
||||
|
||||
RUN set -ex; \
|
||||
\
|
||||
apt-get update; \
|
||||
apt-get install -y --no-install-recommends \
|
||||
openssl \
|
||||
; \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
RUN apk add --update --no-cache openssl bash
|
||||
|
||||
COPY start.sh /usr/bin/
|
||||
RUN chmod +x /usr/bin/start.sh
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
FROM ubuntu:focal
|
||||
|
||||
EXPOSE 3478
|
||||
FROM ubuntu:focal-20220531
|
||||
|
||||
RUN set -ex; \
|
||||
\
|
||||
@@ -49,12 +47,16 @@ RUN chmod +x /usr/bin/start.sh; \
|
||||
sed -i '/TURNSERVER_ENABLED/c\TURNSERVER_ENABLED=1' /etc/default/coturn; \
|
||||
mkdir -p /var/tmp;
|
||||
|
||||
RUN curl -sL -o "/usr/share/janus/lua/json.lua" "https://raw.githubusercontent.com/rxi/json.lua/master/json.lua"; \
|
||||
curl -sL -o "/usr/share/janus/lua/ansicolors.lua" "https://raw.githubusercontent.com/kikito/ansicolors.lua/master/ansicolors.lua"
|
||||
|
||||
RUN mkdir -p /etc/nats; \
|
||||
echo "listen: 127.0.0.1:4222" > /etc/nats/nats.conf; \
|
||||
chown talk:talk /etc; \
|
||||
chown talk:talk -R /etc/nats; \
|
||||
chown talk:talk -R /etc/janus; \
|
||||
chown talk:talk -R /etc/signaling; \
|
||||
chown talk:talk -R /usr/share/janus
|
||||
chown talk:talk -R /usr
|
||||
|
||||
# Give root a random password
|
||||
RUN echo "root:$(openssl rand -base64 12)" | chpasswd
|
||||
|
||||
@@ -17,8 +17,9 @@ fi
|
||||
|
||||
# Turn
|
||||
cat << TURN_CONF > "/etc/turnserver.conf"
|
||||
listening-port=3478
|
||||
listening-port=$TALK_PORT
|
||||
fingerprint
|
||||
lt-cred-mech
|
||||
use-auth-secret
|
||||
static-auth-secret=$TURN_SECRET
|
||||
realm=$NC_DOMAIN
|
||||
@@ -31,37 +32,55 @@ pidfile=/var/tmp/turnserver.pid
|
||||
TURN_CONF
|
||||
|
||||
# Janus
|
||||
sed -i "s|#turn_rest_api_key.*|turn_rest_api_key = $JANUS_API_KEY|" /etc/janus/janus.jcfg
|
||||
sed -i "s|#full_trickle|full_trickle|g" /etc/janus/janus.jcfg
|
||||
set -x
|
||||
sed -i "s|#turn_rest_api_key.*|turn_rest_api_key = \"$JANUS_API_KEY\"|" /etc/janus/janus.jcfg
|
||||
sed -i "s|#full_trickle.*|full_trickle = true|g" /etc/janus/janus.jcfg
|
||||
sed -i 's|#stun_server.*|stun_server = "127.0.0.1"|g' /etc/janus/janus.jcfg
|
||||
sed -i "s|#stun_port.*|stun_port = $TALK_PORT|g" /etc/janus/janus.jcfg
|
||||
sed -i "s|#turn_port.*|turn_port = $TALK_PORT|g" /etc/janus/janus.jcfg
|
||||
sed -i 's|#turn_server.*|turn_server = "127.0.0.1"|g'/etc/janus/janus.jcfg
|
||||
sed -i 's|#turn_type .*|turn_type = "udp"|g' /etc/janus/janus.jcfg
|
||||
sed -i 's|#ice_ignore_list .*|ice_ignore_list = "udp"|g' /etc/janus/janus.jcfg
|
||||
sed -i 's|#interface.*|interface = "lo"|g' /etc/janus/janus.transport.websockets.jcfg
|
||||
sed -i 's|#ws_interface.*|ws_interface = "lo"|g' /etc/janus/janus.transport.websockets.jcfg
|
||||
set +x
|
||||
|
||||
# Signling
|
||||
cat << SIGNALING_CONF > "/etc/signaling/server.conf"
|
||||
[http]
|
||||
listen = 0.0.0.0:8081
|
||||
|
||||
[app]
|
||||
debug = false
|
||||
|
||||
[sessions]
|
||||
hashkey = $(openssl rand -hex 16)
|
||||
blockkey = $(openssl rand -hex 16)
|
||||
|
||||
[clients]
|
||||
internalsecret = $(openssl rand -hex 16)
|
||||
|
||||
[backend]
|
||||
allowed = ${NC_DOMAIN}
|
||||
backends = backend-1
|
||||
allowall = false
|
||||
secret = ${SIGNALING_SECRET}
|
||||
timeout = 10
|
||||
connectionsperhost = 8
|
||||
|
||||
[backend-1]
|
||||
url = https://${NC_DOMAIN}
|
||||
secret = ${SIGNALING_SECRET}
|
||||
|
||||
[nats]
|
||||
url = nats://127.0.0.1:4222
|
||||
|
||||
[mcu]
|
||||
type = janus
|
||||
url = ws://127.0.0.1:8188
|
||||
|
||||
[turn]
|
||||
apikey = ${JANUS_API_KEY}
|
||||
secret = ${TURN_SECRET}
|
||||
servers = turn:$NC_DOMAIN:3478?transport=tcp,turn:$NC_DOMAIN:3478?transport=udp
|
||||
servers = turn:$NC_DOMAIN:$TALK_PORT?transport=tcp,turn:$NC_DOMAIN:$TALK_PORT?transport=udp
|
||||
SIGNALING_CONF
|
||||
|
||||
exec "$@"
|
||||
|
||||
@@ -27,7 +27,7 @@ stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
command=janus
|
||||
command=/usr/bin/janus --config=/etc/janus/janus.jcfg --disable-colors --daemon --log-stdout
|
||||
|
||||
[program:signaling]
|
||||
stdout_logfile=/dev/stdout
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
# From https://github.com/containrrr/watchtower/blob/main/dockerfiles/Dockerfile.self-contained
|
||||
FROM containrrr/watchtower:latest as watchtower
|
||||
FROM containrrr/watchtower:1.4.0 as watchtower
|
||||
|
||||
FROM debian:bullseye
|
||||
|
||||
RUN set -ex; \
|
||||
\
|
||||
apt-get update; \
|
||||
apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
; \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
FROM alpine:3.15.4
|
||||
|
||||
RUN apk add --update --no-cache bash
|
||||
COPY --from=watchtower /watchtower /
|
||||
|
||||
COPY start.sh /
|
||||
|
||||
@@ -16,5 +16,4 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
exec "$@"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
## How to develope the app?
|
||||
## How to develop the app?
|
||||
|
||||
Please note that in order to check if an app is already downloaded
|
||||
Nextcloud will look for a folder with the same name as the app.
|
||||
|
||||
28
develop.md
28
develop.md
@@ -14,24 +14,22 @@ nextcloud/all-in-one:develop
|
||||
And you are done :)
|
||||
It will now also select the developer channel for all other containers automatically.
|
||||
|
||||
## How to publish new releases?
|
||||
Simply use https://github.com/nextcloud/all-in-one/issues/180 as template.
|
||||
|
||||
## How to build new containers
|
||||
|
||||
Go to https://github.com/nextcloud-releases/all-in-one/actions/workflows/repo-sync.yml and run the workflow that will first sync the repo and then build new container that automatically get published to `develop` and `develop-arm64`.
|
||||
|
||||
## How to promote builds from develop to latest
|
||||
## How to promote builds from develop to beta
|
||||
|
||||
To automatically promoted the latest develop version you can use the following script:
|
||||
1. Verify that no job is running here: https://github.com/nextcloud-releases/all-in-one/actions/workflows/build_images.yml
|
||||
2. Go to https://github.com/nextcloud-releases/all-in-one/actions/workflows/promote-to-beta.yml, click on `Run workflow`.
|
||||
|
||||
**WARNING:** Make sure to verify that the latest develop tag is what you really want to deploy since someone could have pushed to main and created a new container in between.
|
||||
```shell
|
||||
# Set the name of the container that you want to promote from the develop- to the latest channels
|
||||
export AIO_NAME=$name
|
||||
# x64
|
||||
docker pull nextcloud/$AIO_NAME\:develop
|
||||
docker tag nextcloud/$AIO_NAME\:develop nextcloud/$AIO_NAME\:latest
|
||||
docker push nextcloud/$AIO_NAME\:latest
|
||||
# arm64
|
||||
docker pull nextcloud/$AIO_NAME\:develop-arm64
|
||||
docker tag nextcloud/$AIO_NAME\:develop-arm64 nextcloud/$AIO_NAME\:latest-arm64
|
||||
docker push nextcloud/$AIO_NAME\:latest-arm64
|
||||
```
|
||||
## How to promote builds from beta to latest
|
||||
|
||||
1. Verify that no job is running here: https://github.com/nextcloud-releases/all-in-one/actions/workflows/promote-to-beta.yml
|
||||
2. Go to https://github.com/nextcloud-releases/all-in-one/actions/workflows/promote-to-latest.yml, click on `Run workflow`.
|
||||
|
||||
## Where to find the VPS and other builds?
|
||||
This is documented here: https://github.com/nextcloud-releases/all-in-one/tree/main/.build
|
||||
|
||||
@@ -2,17 +2,38 @@ version: "3.8"
|
||||
|
||||
volumes:
|
||||
nextcloud_aio_mastercontainer:
|
||||
name: nextcloud_aio_mastercontainer
|
||||
name: nextcloud_aio_mastercontainer # This line is not allowed to be changed
|
||||
|
||||
services:
|
||||
nextcloud:
|
||||
image: nextcloud/all-in-one:latest
|
||||
restart: unless-stopped
|
||||
container_name: nextcloud-aio-mastercontainer
|
||||
image: nextcloud/all-in-one:latest # Must be changed to 'nextcloud/all-in-one:latest-arm64' when used with an arm64 CPU
|
||||
restart: always
|
||||
container_name: nextcloud-aio-mastercontainer # This line is not allowed to be changed
|
||||
volumes:
|
||||
- nextcloud_aio_mastercontainer:/mnt/docker-aio-config
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- nextcloud_aio_mastercontainer:/mnt/docker-aio-config # This line is not allowed to be changed
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro # May be changed on macOS, Windows or docker rootless. See the applicable documentation
|
||||
ports:
|
||||
- 80:80
|
||||
- 80:80 # Can be removed when running behind a reverse proxy. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
|
||||
- 8080:8080
|
||||
- 8443:8443
|
||||
- 8443:8443 # Can be removed when running behind a reverse proxy. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
|
||||
# environment: # Is needed when using any of the options below
|
||||
# - APACHE_PORT=11000 # Is needed when running behind a reverse proxy. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
|
||||
# - APACHE_IP_BINDING=127.0.0.1 # Should be set when running behind a reverse proxy that is running on the same host. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
|
||||
# - TALK_PORT=3478 # This allows to adjust the port that the talk container is using.
|
||||
# - NEXTCLOUD_DATADIR=/mnt/ncdata # Allows to set the host directory for Nextcloud's datadir. See https://github.com/nextcloud/all-in-one#how-to-change-the-default-location-of-nextclouds-datadir
|
||||
# - NEXTCLOUD_MOUNT=/mnt/ # Allows the Nextcloud container to access the chosen directory on the host. See https://github.com/nextcloud/all-in-one#how-to-allow-the-nextcloud-container-to-access-directories-on-the-host
|
||||
# - DOCKER_SOCKET_PATH=/var/run/docker.sock # Needs to be specified if the docker socket on the host is not located in the default '/var/run/docker.sock'. Otherwise mastercontainer updates will fail.
|
||||
|
||||
# # Optional: Caddy reverse proxy. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
|
||||
# # You can find further examples here: https://github.com/nextcloud/all-in-one/discussions/588
|
||||
# caddy:
|
||||
# image: caddy:alpine
|
||||
# restart: always
|
||||
# container_name: caddy
|
||||
# volumes:
|
||||
# - ./Caddyfile:/etc/caddy/Caddyfile
|
||||
# - ./certs:/certs
|
||||
# - ./config:/config
|
||||
# - ./data:/data
|
||||
# - ./sites:/srv
|
||||
# network_mode: "host"
|
||||
|
||||
13
docker-rootless.md
Normal file
13
docker-rootless.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Docker rootless
|
||||
|
||||
You can run AIO with docker rootless by following the steps below.
|
||||
|
||||
0. If docker is already installed, you should consider disabling it first: (`sudo systemctl disable --now docker.service docker.socket`)
|
||||
1. Install docker rootless by following the official documentation: https://docs.docker.com/engine/security/rootless/#install. The easiest way is installing it **Without packages** (`curl -fsSL https://get.docker.com/rootless | sh`). Further limitations, distribution specific hints, etc. are discussed on the same site. Also do not forget to enable the systemd service, which may not be enabled always by default. See https://docs.docker.com/engine/security/rootless/#usage. (`systemctl --user enable docker`)
|
||||
1. If you need ipv6 support, you should enable it by following https://docs.docker.com/config/daemon/ipv6/. The daemon.json file is most likely stored in `~/.config/docker/daemon.json`.
|
||||
1. Do not forget to set the mentioned environmental variables and in best case add them to your `~/.bashrc` file as shown!
|
||||
1. Expose the privileged ports by following https://docs.docker.com/engine/security/rootless/#exposing-privileged-ports. (`sudo setcap cap_net_bind_service=ep $(which rootlesskit); systemctl --user restart docker`)
|
||||
1. Use the official AIO startup command but use `--volume $XDG_RUNTIME_DIR/docker.sock:/var/run/docker.sock:ro` instead of `--volume /var/run/docker.sock:/var/run/docker.sock:ro` and also add `-e DOCKER_SOCKET_PATH=$XDG_RUNTIME_DIR/docker.sock` to the initial container startup (which is needed for mastercontainer updates to work correctly).
|
||||
1. Now everything should work like without docker rootless. You can consider using docker-compose for this or running it behind a reverse proxy. Basically the only thing that needs to be adjusted always in the startup command or docker-compose file (after installing docker rootles) are things that are mentioned in point 3.
|
||||
|
||||
**Please note:** All files outside the containers get created, written to and accessed as the user that is running the docker daemon or a subuid of it. So for the built-in backup to work you need to allow this user to write to the target directory. For changing Nextcloud's datadir, you need to adjust the permissions of the chosen folders to be accessible/writeable by the userid `100032:100032` (if running `grep ^$(whoami): /etc/subuid` as the user that is running the docker daemon returns 100000 as first value). This logically also applies to the NEXTCLOUD_MOUNT option.
|
||||
139
manual-install/latest-arm64.yml
Normal file
139
manual-install/latest-arm64.yml
Normal file
@@ -0,0 +1,139 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
nextcloud-aio-apache:
|
||||
container_name: nextcloud-aio-apache
|
||||
depends_on:
|
||||
- nextcloud-aio-collabora
|
||||
- nextcloud-aio-talk
|
||||
- nextcloud-aio-nextcloud
|
||||
image: nextcloud/aio-apache:latest-arm64
|
||||
ports:
|
||||
- ${APACHE_PORT}:${APACHE_PORT}/tcp
|
||||
environment:
|
||||
- NC_DOMAIN=${NC_DOMAIN}
|
||||
- NEXTCLOUD_HOST=nextcloud-aio-nextcloud
|
||||
- COLLABORA_HOST=nextcloud-aio-collabora
|
||||
- TALK_HOST=nextcloud-aio-talk
|
||||
- APACHE_PORT=${APACHE_PORT}
|
||||
- TZ=${TIMEZONE}
|
||||
volumes:
|
||||
- nextcloud_aio_nextcloud:/var/www/html:ro
|
||||
- nextcloud_aio_apache:/mnt/data:rw
|
||||
stop_grace_period: 10s
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- nextcloud-aio
|
||||
|
||||
nextcloud-aio-database:
|
||||
container_name: nextcloud-aio-database
|
||||
image: nextcloud/aio-postgresql:latest-arm64
|
||||
volumes:
|
||||
- nextcloud_aio_database:/var/lib/postgresql/data:rw
|
||||
- nextcloud_aio_database_dump:/mnt/data:rw
|
||||
environment:
|
||||
- POSTGRES_PASSWORD=${DATABASE_PASSWORD}
|
||||
- POSTGRES_DB=nextcloud_database
|
||||
- POSTGRES_USER=nextcloud
|
||||
- TZ=${TIMEZONE}
|
||||
- PGTZ=${TIMEZONE}
|
||||
stop_grace_period: 1800s
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- nextcloud-aio
|
||||
|
||||
nextcloud-aio-nextcloud:
|
||||
container_name: nextcloud-aio-nextcloud
|
||||
depends_on:
|
||||
- nextcloud-aio-database
|
||||
- nextcloud-aio-redis
|
||||
image: nextcloud/aio-nextcloud:latest-arm64
|
||||
volumes:
|
||||
- nextcloud_aio_nextcloud:/var/www/html:rw
|
||||
- ${NEXTCLOUD_DATADIR}:/mnt/ncdata:rw
|
||||
- ${NEXTCLOUD_MOUNT}:${NEXTCLOUD_MOUNT}:rw
|
||||
environment:
|
||||
- POSTGRES_HOST=nextcloud-aio-database
|
||||
- POSTGRES_PASSWORD=${DATABASE_PASSWORD}
|
||||
- POSTGRES_DB=nextcloud_database
|
||||
- POSTGRES_USER=nextcloud
|
||||
- REDIS_HOST=nextcloud-aio-redis
|
||||
- REDIS_HOST_PASSWORD=${REDIS_PASSWORD}
|
||||
- AIO_TOKEN=${AIO_TOKEN}
|
||||
- NC_DOMAIN=${NC_DOMAIN}
|
||||
- ADMIN_USER=admin
|
||||
- ADMIN_PASSWORD=${NEXTCLOUD_PASSWORD}
|
||||
- NEXTCLOUD_DATA_DIR=/mnt/ncdata
|
||||
- OVERWRITEHOST=${NC_DOMAIN}
|
||||
- OVERWRITEPROTOCOL=https
|
||||
- TURN_SECRET=${TURN_SECRET}
|
||||
- SIGNALING_SECRET=${SIGNALING_SECRET}
|
||||
- AIO_URL=${AIO_URL}
|
||||
- NEXTCLOUD_MOUNT=${NEXTCLOUD_MOUNT}
|
||||
- COLLABORA_ENABLED=${COLLABORA_ENABLED}
|
||||
- COLLABORA_HOST=nextcloud-aio-collabora
|
||||
- TALK_ENABLED=${TALK_ENABLED}
|
||||
- DAILY_BACKUP_RUNNING=${DAILY_BACKUP_RUNNING}
|
||||
- TZ=${TIMEZONE}
|
||||
- TALK_PORT=${TALK_PORT}
|
||||
stop_grace_period: 10s
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- nextcloud-aio
|
||||
|
||||
nextcloud-aio-redis:
|
||||
container_name: nextcloud-aio-redis
|
||||
image: nextcloud/aio-redis:latest-arm64
|
||||
environment:
|
||||
- REDIS_HOST_PASSWORD=${REDIS_PASSWORD}
|
||||
- TZ=${TIMEZONE}
|
||||
stop_grace_period: 10s
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- nextcloud-aio
|
||||
|
||||
nextcloud-aio-collabora:
|
||||
container_name: nextcloud-aio-collabora
|
||||
image: nextcloud/aio-collabora:latest-arm64
|
||||
environment:
|
||||
- aliasgroup1=https://${NC_DOMAIN}:443
|
||||
- extra_params=--o:ssl.enable=false --o:ssl.termination=true --o:logging.level=warning
|
||||
- dictionaries=${COLLABORA_DICTIONARIES}
|
||||
- TZ=${TIMEZONE}
|
||||
stop_grace_period: 10s
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- nextcloud-aio
|
||||
|
||||
nextcloud-aio-talk:
|
||||
container_name: nextcloud-aio-talk
|
||||
image: nextcloud/aio-talk:latest-arm64
|
||||
ports:
|
||||
- ${TALK_PORT}:${TALK_PORT}/tcp
|
||||
- ${TALK_PORT}:${TALK_PORT}/udp
|
||||
environment:
|
||||
- NC_DOMAIN=${NC_DOMAIN}
|
||||
- TURN_SECRET=${TURN_SECRET}
|
||||
- SIGNALING_SECRET=${SIGNALING_SECRET}
|
||||
- JANUS_API_KEY=${JANUS_API_KEY}
|
||||
- TZ=${TIMEZONE}
|
||||
- TALK_PORT=${TALK_PORT}
|
||||
stop_grace_period: 10s
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- nextcloud-aio
|
||||
|
||||
volumes:
|
||||
nextcloud_aio_apache:
|
||||
name: nextcloud_aio_apache
|
||||
nextcloud_aio_database:
|
||||
name: nextcloud_aio_database
|
||||
nextcloud_aio_database_dump:
|
||||
name: nextcloud_aio_database_dump
|
||||
nextcloud_aio_nextcloud:
|
||||
name: nextcloud_aio_nextcloud
|
||||
nextcloud_aio_nextcloud_data:
|
||||
name: nextcloud_aio_nextcloud_data
|
||||
|
||||
networks:
|
||||
nextcloud-aio:
|
||||
178
manual-install/latest.yml
Normal file
178
manual-install/latest.yml
Normal file
@@ -0,0 +1,178 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
nextcloud-aio-apache:
|
||||
container_name: nextcloud-aio-apache
|
||||
depends_on:
|
||||
- nextcloud-aio-onlyoffice
|
||||
- nextcloud-aio-collabora
|
||||
- nextcloud-aio-clamav
|
||||
- nextcloud-aio-talk
|
||||
- nextcloud-aio-nextcloud
|
||||
image: nextcloud/aio-apache:latest
|
||||
ports:
|
||||
- ${APACHE_PORT}:${APACHE_PORT}/tcp
|
||||
environment:
|
||||
- NC_DOMAIN=${NC_DOMAIN}
|
||||
- NEXTCLOUD_HOST=nextcloud-aio-nextcloud
|
||||
- COLLABORA_HOST=nextcloud-aio-collabora
|
||||
- TALK_HOST=nextcloud-aio-talk
|
||||
- APACHE_PORT=${APACHE_PORT}
|
||||
- ONLYOFFICE_HOST=nextcloud-aio-onlyoffice
|
||||
- TZ=${TIMEZONE}
|
||||
volumes:
|
||||
- nextcloud_aio_nextcloud:/var/www/html:ro
|
||||
- nextcloud_aio_apache:/mnt/data:rw
|
||||
stop_grace_period: 10s
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- nextcloud-aio
|
||||
|
||||
nextcloud-aio-database:
|
||||
container_name: nextcloud-aio-database
|
||||
image: nextcloud/aio-postgresql:latest
|
||||
volumes:
|
||||
- nextcloud_aio_database:/var/lib/postgresql/data:rw
|
||||
- nextcloud_aio_database_dump:/mnt/data:rw
|
||||
environment:
|
||||
- POSTGRES_PASSWORD=${DATABASE_PASSWORD}
|
||||
- POSTGRES_DB=nextcloud_database
|
||||
- POSTGRES_USER=nextcloud
|
||||
- TZ=${TIMEZONE}
|
||||
- PGTZ=${TIMEZONE}
|
||||
stop_grace_period: 1800s
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- nextcloud-aio
|
||||
|
||||
nextcloud-aio-nextcloud:
|
||||
container_name: nextcloud-aio-nextcloud
|
||||
depends_on:
|
||||
- nextcloud-aio-database
|
||||
- nextcloud-aio-redis
|
||||
image: nextcloud/aio-nextcloud:latest
|
||||
volumes:
|
||||
- nextcloud_aio_nextcloud:/var/www/html:rw
|
||||
- ${NEXTCLOUD_DATADIR}:/mnt/ncdata:rw
|
||||
- ${NEXTCLOUD_MOUNT}:${NEXTCLOUD_MOUNT}:rw
|
||||
environment:
|
||||
- POSTGRES_HOST=nextcloud-aio-database
|
||||
- POSTGRES_PASSWORD=${DATABASE_PASSWORD}
|
||||
- POSTGRES_DB=nextcloud_database
|
||||
- POSTGRES_USER=nextcloud
|
||||
- REDIS_HOST=nextcloud-aio-redis
|
||||
- REDIS_HOST_PASSWORD=${REDIS_PASSWORD}
|
||||
- AIO_TOKEN=${AIO_TOKEN}
|
||||
- NC_DOMAIN=${NC_DOMAIN}
|
||||
- ADMIN_USER=admin
|
||||
- ADMIN_PASSWORD=${NEXTCLOUD_PASSWORD}
|
||||
- NEXTCLOUD_DATA_DIR=/mnt/ncdata
|
||||
- OVERWRITEHOST=${NC_DOMAIN}
|
||||
- OVERWRITEPROTOCOL=https
|
||||
- TURN_SECRET=${TURN_SECRET}
|
||||
- SIGNALING_SECRET=${SIGNALING_SECRET}
|
||||
- ONLYOFFICE_SECRET=${ONLYOFFICE_SECRET}
|
||||
- AIO_URL=${AIO_URL}
|
||||
- NEXTCLOUD_MOUNT=${NEXTCLOUD_MOUNT}
|
||||
- CLAMAV_ENABLED=${CLAMAV_ENABLED}
|
||||
- CLAMAV_HOST=nextcloud-aio-clamav
|
||||
- ONLYOFFICE_ENABLED=${ONLYOFFICE_ENABLED}
|
||||
- COLLABORA_ENABLED=${COLLABORA_ENABLED}
|
||||
- COLLABORA_HOST=nextcloud-aio-collabora
|
||||
- TALK_ENABLED=${TALK_ENABLED}
|
||||
- ONLYOFFICE_HOST=nextcloud-aio-onlyoffice
|
||||
- DAILY_BACKUP_RUNNING=${DAILY_BACKUP_RUNNING}
|
||||
- TZ=${TIMEZONE}
|
||||
- TALK_PORT=${TALK_PORT}
|
||||
stop_grace_period: 10s
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- nextcloud-aio
|
||||
|
||||
nextcloud-aio-redis:
|
||||
container_name: nextcloud-aio-redis
|
||||
image: nextcloud/aio-redis:latest
|
||||
environment:
|
||||
- REDIS_HOST_PASSWORD=${REDIS_PASSWORD}
|
||||
- TZ=${TIMEZONE}
|
||||
stop_grace_period: 10s
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- nextcloud-aio
|
||||
|
||||
nextcloud-aio-collabora:
|
||||
container_name: nextcloud-aio-collabora
|
||||
image: nextcloud/aio-collabora:latest
|
||||
environment:
|
||||
- aliasgroup1=https://${NC_DOMAIN}:443
|
||||
- extra_params=--o:ssl.enable=false --o:ssl.termination=true --o:logging.level=warning
|
||||
- dictionaries=${COLLABORA_DICTIONARIES}
|
||||
- TZ=${TIMEZONE}
|
||||
stop_grace_period: 10s
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- nextcloud-aio
|
||||
|
||||
nextcloud-aio-talk:
|
||||
container_name: nextcloud-aio-talk
|
||||
image: nextcloud/aio-talk:latest
|
||||
ports:
|
||||
- ${TALK_PORT}:${TALK_PORT}/tcp
|
||||
- ${TALK_PORT}:${TALK_PORT}/udp
|
||||
environment:
|
||||
- NC_DOMAIN=${NC_DOMAIN}
|
||||
- TURN_SECRET=${TURN_SECRET}
|
||||
- SIGNALING_SECRET=${SIGNALING_SECRET}
|
||||
- JANUS_API_KEY=${JANUS_API_KEY}
|
||||
- TZ=${TIMEZONE}
|
||||
- TALK_PORT=${TALK_PORT}
|
||||
stop_grace_period: 10s
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- nextcloud-aio
|
||||
|
||||
nextcloud-aio-clamav:
|
||||
container_name: nextcloud-aio-clamav
|
||||
image: nextcloud/aio-clamav:latest
|
||||
environment:
|
||||
- TZ=${TIMEZONE}
|
||||
volumes:
|
||||
- nextcloud_aio_clamav:/var/lib/clamav:rw
|
||||
stop_grace_period: 10s
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- nextcloud-aio
|
||||
|
||||
nextcloud-aio-onlyoffice:
|
||||
container_name: nextcloud-aio-onlyoffice
|
||||
image: nextcloud/aio-onlyoffice:latest
|
||||
environment:
|
||||
- TZ=${TIMEZONE}
|
||||
- JWT_ENABLED=true
|
||||
- JWT_HEADER=AuthorizationJwt
|
||||
- JWT_SECRET=${ONLYOFFICE_SECRET}
|
||||
volumes:
|
||||
- nextcloud_aio_onlyoffice:/var/lib/onlyoffice:rw
|
||||
stop_grace_period: 10s
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- nextcloud-aio
|
||||
|
||||
volumes:
|
||||
nextcloud_aio_apache:
|
||||
name: nextcloud_aio_apache
|
||||
nextcloud_aio_clamav:
|
||||
name: nextcloud_aio_clamav
|
||||
nextcloud_aio_database:
|
||||
name: nextcloud_aio_database
|
||||
nextcloud_aio_database_dump:
|
||||
name: nextcloud_aio_database_dump
|
||||
nextcloud_aio_nextcloud:
|
||||
name: nextcloud_aio_nextcloud
|
||||
nextcloud_aio_onlyoffice:
|
||||
name: nextcloud_aio_onlyoffice
|
||||
nextcloud_aio_nextcloud_data:
|
||||
name: nextcloud_aio_nextcloud_data
|
||||
|
||||
networks:
|
||||
nextcloud-aio:
|
||||
41
manual-install/readme.md
Normal file
41
manual-install/readme.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Manual installation
|
||||
|
||||
You can run the containers that are build for AIO with docker-compose. This comes with a few downsides, that are discussed below.
|
||||
|
||||
### Advantages
|
||||
- You can run it without a container having access to the docker socket
|
||||
- You can modify all values on your own
|
||||
|
||||
### Disadvantages
|
||||
- You loose the AIO interface
|
||||
- You loose update notifications and automatic updates
|
||||
- You loose all AIO backup and restore features
|
||||
- You need to know what you are doing, especially when modifying the docker-compose file
|
||||
- Probably more
|
||||
|
||||
## How to use this?
|
||||
First, install docker and docker-compose if not already done. Then simply run the following:
|
||||
```bash
|
||||
git clone https://github.com/nextcloud/all-in-one.git
|
||||
cd all-in-one/manual-install
|
||||
```
|
||||
Then copy the sample.conf to a new file, e.g. `cp sample.conf my.conf`, open the new conf file, e.g. with `nano my.conf`, edit all values that are marked with `# TODO!`, close and save the file.
|
||||
|
||||
Now copy the provided yaml file to a docker-compose file by running on x64 `cp latest.yml docker-compose.yml` and on arm64 `cp latest-arm64.yml docker-compose.yml`.
|
||||
|
||||
Now you should be ready to go with `sudo docker-compose --env-file my.conf up`.
|
||||
|
||||
## How to update?
|
||||
Since the AIO containers may change in the future, it is highly recommended to strictly follow the following procedure whenever you want to upgrade your containers.
|
||||
1. Run `sudo docker-compose --env-file my.conf down` to stop all running containers
|
||||
1. Back up all important files and folders
|
||||
1. Run `git pull` in order to get the updated yaml files from the repository. Now bring your `docker-compose.yml` file up-to-date with the updated one from the repository. You can use `diff docker-compose.yml latest.yml` on x64 and `diff docker-compose.yml latest-arm64.yml` on arm64 for comparing.
|
||||
1. Also have a look at the `sample.conf` if any variable was added or renamed and add that to your conf file as well. Here may help the diff command as well.
|
||||
1. After the file update was successful, simply run `sudo docker-compose --env-file my.conf pull` to pull the new images.
|
||||
1. At the end run `sudo docker-compose --env-file my.conf up` in order to start and update the containers with the new configuration.
|
||||
|
||||
## FAQ
|
||||
### Backup and restore?
|
||||
If you leave `NEXTCLOUD_DATADIR` in your conf file at the default value of `nextcloud_aio_nextcloud_data` and don't modify the yaml file, all data will be stored inside docker volumes which are on Linux by default located here: `/var/lib/docker/volumes`. Simply backing up this location should be a valid backup solution. Then you can also easily restore in case something bad happens. However if you change `NEXTCLOUD_DATADIR` to a path like `/mnt/ncdata`, you obviously need to back up this location, too because the Nextcloud data will be stored there. The same applies to any change to the yaml file.
|
||||
|
||||
Obviously you also need to back up the conf file and the yaml file if you modified it.
|
||||
21
manual-install/sample.conf
Normal file
21
manual-install/sample.conf
Normal file
@@ -0,0 +1,21 @@
|
||||
AIO_TOKEN=123456 # Has no function but needs to be set!
|
||||
AIO_URL=localhost # Has no function but needs to be set!
|
||||
APACHE_PORT=443 # Changing this to a different value than 443 will allow you to run it behind a reverse proxy.
|
||||
CLAMAV_ENABLED=no # Setting this to "yes" enables the option in Nextcloud automatically.
|
||||
COLLABORA_DICTIONARIES=de_DE en_GB en_US es_ES fr_FR it nl pt_BR pt_PT ru # You can change this in order to enable other dictionaries for collabora
|
||||
COLLABORA_ENABLED=yes # Setting this to "yes" enables the option in Nextcloud automatically.
|
||||
DAILY_BACKUP_RUNNING=no # When setting to yes, it will automatically update all installed Nextcloud apps upon container startup.
|
||||
DATABASE_PASSWORD= # TODO! This needs to be a unique and good password!
|
||||
JANUS_API_KEY= # TODO! This needs to be a unique and good password!
|
||||
NC_DOMAIN=yourdomain.com # TODO! Needs to be changed to the domain that you want to use for Nextcloud.
|
||||
NEXTCLOUD_DATADIR=nextcloud_aio_nextcloud_data # You can change this to e.g. "/mnt/ncdata" to map it to a location on your host. It needs to be adjusted before the first startup and never afterwards!
|
||||
NEXTCLOUD_MOUNT=/mnt/ # This allows the Nextcloud container to access directories on the host. It must never be equal to the value of NEXTCLOUD_DATADIR!
|
||||
NEXTCLOUD_PASSWORD= # TODO! This is the password of the initially created Nextcloud admin with username "admin".
|
||||
ONLYOFFICE_ENABLED=no # Setting this to "yes" enables the option in Nextcloud automatically.
|
||||
ONLYOFFICE_SECRET= # TODO! This needs to be a unique and good password!
|
||||
REDIS_PASSWORD= # TODO! This needs to be a unique and good password!
|
||||
SIGNALING_SECRET= # TODO! This needs to be a unique and good password!
|
||||
TALK_ENABLED=yes # Setting this to "yes" enables the option in Nextcloud automatically.
|
||||
TALK_PORT=3478 # This allows to adjust the port that the talk container is using.
|
||||
TIMEZONE=Europe/Berlin # TODO! This is the timezone that your containers will use.
|
||||
TURN_SECRET= # TODO! This needs to be a unique and good password!
|
||||
126
manual-install/update-yaml.sh
Normal file
126
manual-install/update-yaml.sh
Normal file
@@ -0,0 +1,126 @@
|
||||
#!/bin/bash
|
||||
|
||||
jq -c . ./php/containers.json > /tmp/containers.json
|
||||
sed -i 's|","location":"|:|g' /tmp/containers.json
|
||||
sed -i 's|","writeable":false|:ro"|g' /tmp/containers.json
|
||||
sed -i 's|","writeable":true|:rw"|g' /tmp/containers.json
|
||||
OUTPUT="$(cat /tmp/containers.json)"
|
||||
OUTPUT="$(echo "$OUTPUT" | jq 'del(.production[].internalPorts)')"
|
||||
OUTPUT="$(echo "$OUTPUT" | jq 'del(.production[].secrets)')"
|
||||
OUTPUT="$(echo "$OUTPUT" | jq 'del(.production[] | select(.identifier == "nextcloud-aio-watchtower"))')"
|
||||
OUTPUT="$(echo "$OUTPUT" | jq 'del(.production[] | select(.identifier == "nextcloud-aio-domaincheck"))')"
|
||||
OUTPUT="$(echo "$OUTPUT" | jq 'del(.production[] | select(.identifier == "nextcloud-aio-borgbackup"))')"
|
||||
|
||||
snap install yq
|
||||
mkdir -p ./manual-install
|
||||
echo "$OUTPUT" | yq -P > ./manual-install/containers.yml
|
||||
|
||||
cd manual-install || exit
|
||||
sed -i "s|'||g" containers.yml
|
||||
sed -i 's|production:|services:|' containers.yml
|
||||
sed -i 's|- identifier:| container_name:|' containers.yml
|
||||
sed -i 's|restartPolicy:|restart:|' containers.yml
|
||||
sed -i 's|environmentVariables:|environment:|' containers.yml
|
||||
sed -i '/displayName:/d' containers.yml
|
||||
sed -i 's|maxShutdownTime:|stop_grace_period:|' containers.yml
|
||||
sed -i '/stop_grace_period:/s/$/s/' containers.yml
|
||||
sed -i 's|containerName:|image:|' containers.yml
|
||||
sed -i '/: \[\]/d' containers.yml
|
||||
sed -i 's|dependsOn:|depends_on:|' containers.yml
|
||||
sed -i 's|- name: |- |' containers.yml
|
||||
|
||||
TCP="$(grep -oP '[%A-Z0-9_]+/tcp' containers.yml | sort -u)"
|
||||
mapfile -t TCP <<< "$TCP"
|
||||
for port in "${TCP[@]}"
|
||||
do
|
||||
solve_port="${port%%/tcp}"
|
||||
sed -i "s|$port|$solve_port:$solve_port/tcp|" containers.yml
|
||||
done
|
||||
|
||||
UDP="$(grep -oP '[%A-Z0-9_]+/udp' containers.yml | sort -u)"
|
||||
mapfile -t UDP <<< "$UDP"
|
||||
for port in "${UDP[@]}"
|
||||
do
|
||||
solve_port="${port%%/udp}"
|
||||
sed -i "s|$port|$solve_port:$solve_port/udp|" containers.yml
|
||||
done
|
||||
|
||||
rm -f sample.conf
|
||||
VARIABLES="$(grep -oP '%[A-Z_a-z0-6]+%' containers.yml | sort -u)"
|
||||
mapfile -t VARIABLES <<< "$VARIABLES"
|
||||
for variable in "${VARIABLES[@]}"
|
||||
do
|
||||
# shellcheck disable=SC2001
|
||||
sole_variable="$(echo "$variable" | sed 's|%||g')"
|
||||
echo "$sole_variable=" >> sample.conf
|
||||
sed -i "s|$variable|\${$sole_variable}|g" containers.yml
|
||||
done
|
||||
|
||||
sed -i 's|_ENABLED=|_ENABLED=no # Setting this to "yes" enables the option in Nextcloud automatically.|' sample.conf
|
||||
sed -i 's|TALK_ENABLED=no|TALK_ENABLED=yes|' sample.conf
|
||||
sed -i 's|COLLABORA_ENABLED=no|COLLABORA_ENABLED=yes|' sample.conf
|
||||
sed -i 's|COLLABORA_DICTIONARIES=|COLLABORA_DICTIONARIES=de_DE en_GB en_US es_ES fr_FR it nl pt_BR pt_PT ru # You can change this in order to enable other dictionaries for collabora|' sample.conf
|
||||
sed -i 's|NEXTCLOUD_DATADIR=|NEXTCLOUD_DATADIR=nextcloud_aio_nextcloud_data # You can change this to e.g. "/mnt/ncdata" to map it to a location on your host. It needs to be adjusted before the first startup and never afterwards!|' sample.conf
|
||||
sed -i 's|NEXTCLOUD_MOUNT=|NEXTCLOUD_MOUNT=/mnt/ # This allows the Nextcloud container to access directories on the host. It must never be equal to the value of NEXTCLOUD_DATADIR!|' sample.conf
|
||||
sed -i 's|UPDATE_NEXTCLOUD_APPS=|UPDATE_NEXTCLOUD_APPS=no # When setting to yes, it will automatically update all installed Nextcloud apps upon container startup.|' sample.conf
|
||||
sed -i 's|APACHE_PORT=|APACHE_PORT=443 # Changing this to a different value than 443 will allow you to run it behind a reverse proxy.|' sample.conf
|
||||
sed -i 's|TALK_PORT=|TALK_PORT=3478 # This allows to adjust the port that the talk container is using.|' sample.conf
|
||||
sed -i 's|AIO_TOKEN=|AIO_TOKEN=123456 # Has no function but needs to be set!|' sample.conf
|
||||
sed -i 's|AIO_URL=|AIO_URL=localhost # Has no function but needs to be set!|' sample.conf
|
||||
sed -i 's|NC_DOMAIN=|NC_DOMAIN=yourdomain.com # TODO! Needs to be changed to the domain that you want to use for Nextcloud.|' sample.conf
|
||||
sed -i 's|NEXTCLOUD_PASSWORD=|NEXTCLOUD_PASSWORD= # TODO! This is the password of the initially created Nextcloud admin with username "admin".|' sample.conf
|
||||
sed -i 's|TIMEZONE=|TIMEZONE=Europe/Berlin # TODO! This is the timezone that your containers will use.|' sample.conf
|
||||
sed -i 's|=$|= # TODO! This needs to be a unique and good password!|' sample.conf
|
||||
|
||||
cat sample.conf
|
||||
|
||||
OUTPUT="$(cat containers.yml)"
|
||||
NAMES="$(grep -oP "container_name:.*" containers.yml | grep -oP 'nextcloud-aio.*')"
|
||||
mapfile -t NAMES <<< "$NAMES"
|
||||
for name in "${NAMES[@]}"
|
||||
do
|
||||
OUTPUT="$(echo "$OUTPUT" | sed "/container_name.*$name/i\ \ $name:")"
|
||||
if [ "$name" != "nextcloud-aio-apache" ]; then
|
||||
OUTPUT="$(echo "$OUTPUT" | sed "/ $name:/i\ ")"
|
||||
fi
|
||||
done
|
||||
|
||||
OUTPUT="$(echo "$OUTPUT" | sed "/restart: /a\ \ \ \ networks:\n\ \ \ \ \ \ - nextcloud-aio")"
|
||||
|
||||
echo 'version: "3.8"' > containers.yml
|
||||
echo "" >> containers.yml
|
||||
|
||||
echo "$OUTPUT" >> containers.yml
|
||||
|
||||
VOLUMES="$(grep -oP 'nextcloud_aio_[a-z_]+' containers.yml | sort -u)"
|
||||
mapfile -t VOLUMES <<< "$VOLUMES"
|
||||
echo "" >> containers.yml
|
||||
echo "volumes:" >> containers.yml
|
||||
for volume in "${VOLUMES[@]}" "nextcloud_aio_nextcloud_data"
|
||||
do
|
||||
cat << VOLUMES >> containers.yml
|
||||
$volume:
|
||||
name: $volume
|
||||
VOLUMES
|
||||
done
|
||||
|
||||
cat << NETWORK >> containers.yml
|
||||
|
||||
networks:
|
||||
nextcloud-aio:
|
||||
NETWORK
|
||||
|
||||
cat containers.yml > latest.yml
|
||||
sed -i '/image:/s/$/:latest/' latest.yml
|
||||
|
||||
cat containers.yml > latest-arm64.yml
|
||||
sed -i '/image:/s/$/:latest-arm64/' latest-arm64.yml
|
||||
sed -i '/ nextcloud-aio-clamav:/,/^$/d' latest-arm64.yml
|
||||
sed -i '/nextcloud[-_]aio[-_]clamav/d' latest-arm64.yml
|
||||
sed -i '/CLAMAV_ENABLED/d' latest-arm64.yml
|
||||
sed -i '/ nextcloud-aio-onlyoffice:/,/^$/d' latest-arm64.yml
|
||||
sed -i '/nextcloud[-_]aio[-_]onlyoffice/d' latest-arm64.yml
|
||||
sed -i '/ONLYOFFICE_ENABLED/d' latest-arm64.yml
|
||||
sed -i '/ONLYOFFICE_SECRET/d' latest-arm64.yml
|
||||
|
||||
rm containers.yml
|
||||
25
manual-upgrade.md
Normal file
25
manual-upgrade.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Manual upgrade
|
||||
|
||||
If you do not install any upgrade for around 6-12 months or longer, it can happen that your instance is so outdated that in the meantime the PHP version of the Nextcloud container got bumped to a version that is not compatible with your currently installed Nextcloud version which means that after doing an upgrade after this long time, Nextcloud will suddenly not work anymore. There is unfortunately no way to fix this from the maintainer side if you refrain from upgrading for so long.
|
||||
|
||||
The only way to fix this on your side is upgrading regularly (e.g. by enabling daily backups which will also automatically upgrade all containers) and following the steps below:
|
||||
|
||||
1. Start all containers from the aio interface (now, it will report that Nextcloud is restarting because it is not able to start due to the above mentioned problem)
|
||||
1. Do **not** click on `Stop containers` because you will need them running going forward, see below
|
||||
1. Stop the Nextcloud container and the Apache container by running `sudo docker stop nextcloud-aio-nextcloud && sudo docker stop nextcloud-aio-apache`.
|
||||
1. Find out with which PHP version your installed Nextcloud is compatible by running `sudo cat /var/lib/docker/volumes/nextcloud_aio_nextcloud/_data/lib/versioncheck.php`. (There you will find information about the max. supported PHP version.)
|
||||
1. Run the following commands in order to reverse engineer the Nextcloud container:
|
||||
```bash
|
||||
sudo docker pull assaflavie/runlike
|
||||
echo '#/bin/bash' > /tmp/nextcloud-aio-nextcloud
|
||||
sudo docker run --rm -v /var/run/docker.sock:/var/run/docker.sock assaflavie/runlike -p nextcloud-aio-nextcloud >> /tmp/nextcloud-aio-nextcloud
|
||||
sudo chown root:root /tmp/nextcloud-aio-nextcloud
|
||||
```
|
||||
1. Now open the file with e.g. nano: `sudo nano /tmp/nextcloud-aio-nextcloud` and change the line that should probably be `nextcloud/aio-nextcloud:latest` on x64 or `nextcloud/aio-nextcloud:latest-arm64` on arm64 to the highest compatible PHP version: E.g. `nextcloud/aio-nextcloud:php8.0-latest` on x64 or `nextcloud/aio-nextcloud:php8.0-latest-arm64` on arm64. Then save the file and close it with `[Ctrl]+[o]` -> `[Enter]` and `[Ctrl]+[x]`.
|
||||
1. After doing so, remove the Nextcloud container with `sudo docker rm nextcloud-aio-nextcloud`.
|
||||
1. Now start the Nextcloud container with the new tag by simply running `sudo bash /tmp/nextcloud-aio-nextcloud` which at startup should automatically upgrade Nextcloud to a more recent version. If not, make sure that there is no `skip.update` file in the Nextcloud datadir. If there is such a file, simply delete the file and restart the container again.<br>
|
||||
**Info**: You can open the Nextcloud container logs with `sudo docker logs -f nextcloud-aio-nextcloud`.
|
||||
1. After the Nextcloud container is started (you can tell by looking at the logs), simply restart the container again with `sudo docker restart nextcloud-aio-nextcloud` until it does not install a new Nextcloud update anymore upon the container startup.
|
||||
1. Now, you should be able to use the AIO interface again by simply stopping the AIO containers and starting them again which should finally bring up your instance again.
|
||||
1. If not and if you get the same error again, you may repeat the process starting from the beginning again until your Nextcloud version is finally up-to-date.
|
||||
1. Now, if everything is finally running as usual again, it is recommended to create a backup in order to save the current state. Also you should think about enabling daily backups if doing regularl upgrades is too much effort for you.
|
||||
18
migration.md
18
migration.md
@@ -1,11 +1,11 @@
|
||||
## How to migrate from an already existing Nextcloud installation to Nextcloud AIO?
|
||||
# How to migrate from an already existing Nextcloud installation to Nextcloud AIO?
|
||||
|
||||
There are basically two ways how to migrate from an already existing Nextcloud installation to Nextcloud AIO:
|
||||
|
||||
1. Migrate only the files which is the easiest way
|
||||
1. Migrate the files and the database which is much more complicated
|
||||
|
||||
### Migrate only the files
|
||||
## Migrate only the files
|
||||
**Please note**: If you used groupfolders or encrypted your files before, you will need to restore the database, as well!
|
||||
|
||||
The procedure for migrating only the files works like this:
|
||||
@@ -14,16 +14,16 @@ The procedure for migrating only the files works like this:
|
||||
1. Recreate all users that were present on your former installation
|
||||
1. Take a backup using Nextcloud AIO's built-in backup solution (so that you can easily restore to this state again) (Note: this will stop all containers and is expected: don't start the container again at this point!)
|
||||
1. Restore the datadirectory of your former instance into the following directory: `/var/lib/docker/volumes/nextcloud_aio_nextcloud_data/_data/`
|
||||
1. Next, run `sudo chown -R 33:0 /var/lib/docker/volumes/nextcloud_aio_nextcloud_data/_data/*` to apply the correct permissions
|
||||
1. Next, run `sudo chown -R 33:0 /var/lib/docker/volumes/nextcloud_aio_nextcloud_data/_data/*` and `sudo chmod -R 750 /var/lib/docker/volumes/nextcloud_aio_nextcloud_data/_data/*` to apply the correct permissions
|
||||
1. Start the containers again and wait until all containers are running
|
||||
1. Run `sudo docker exec -it nextcloud-aio-nextcloud php occ files:scan-app-data && sudo docker exec -it nextcloud-aio-nextcloud php occ files:scan --all` in order to scan all files in the datadirectory.
|
||||
|
||||
### Migrate the files and the database
|
||||
## Migrate the files and the database
|
||||
**Please note**: this is much more complicated than migrating only the files and also not as failproof so be warned!<br>
|
||||
Also, you will currently not be able to use local external storage in Nextcloud AIO since that is not supported, yet. See https://github.com/nextcloud/all-in-one/issues/76
|
||||
|
||||
The procedure for migrating the files and the database works like this:
|
||||
1. Make sure that your old instance is on exactly the same version like the version used in Nextcloud AIO. (e.g. 23.0.0) If not, simply upgrade your former installation to that version or wait until the version used in Nextcloud AIO got updated to the same version of your former installation or the other way around.
|
||||
1. Make sure that your old instance is on exactly the same version like the version used in Nextcloud AIO. (e.g. 23.0.0) You can find the used version here: [click here](https://github.com/nextcloud/all-in-one/search?l=Dockerfile&q=NEXTCLOUD_VERSION&type=). If not, simply upgrade your former installation to that version or wait until the version used in Nextcloud AIO got updated to the same version of your former installation or the other way around.
|
||||
1. Take a backup of your former instance (especially from your datadirectory and database)
|
||||
1. If your former installation didn't use Postgresql already, you will now need to convert your old installation to use Postgresql as database temporarily (in order to be able to perform a pg_dump afterwards):
|
||||
1. Install Postgresql on your former installation: on a Debian based OS should the following command work:
|
||||
@@ -36,13 +36,13 @@ The procedure for migrating the files and the database works like this:
|
||||
export PG_PASSWORD="my-temporary-password"
|
||||
export PG_DATABASE="nextcloud_db"
|
||||
sudo -u postgres psql <<END
|
||||
CREATE USER $PG_USER WITH PASSWORD '$PGDB_PASS';
|
||||
CREATE USER $PG_USER WITH PASSWORD '$PG_PASSWORD';
|
||||
CREATE DATABASE $PG_DATABASE WITH OWNER $PG_USER TEMPLATE template0 ENCODING 'UTF8';
|
||||
END
|
||||
```
|
||||
1. Run the following command to start the conversion:
|
||||
```
|
||||
occ db:convert-type --all-apps pgsql "$PG_USER" 127.0.0.1 "$PG_DATABASE"
|
||||
occ db:convert-type --all-apps --password "$PG_PASSWORD" pgsql "$PG_USER" 127.0.0.1 "$PG_DATABASE"
|
||||
```
|
||||
**Please note:** You might need to change the ip-address `127.0.0.1` based on your exact installation.<br>
|
||||
Further information on the conversion is additionally available here: https://docs.nextcloud.com/server/stable/admin_manual/configuration_database/db_conversion.html#converting-database-type
|
||||
@@ -54,7 +54,7 @@ The procedure for migrating the files and the database works like this:
|
||||
```
|
||||
**Please note:** The exact name of the database export file is important! (`database-dump.sql`)<br>
|
||||
And of course you need to to use the correct name that the Postgresql database has for the export (if `$PG_DATABASE` doesn't work directly).
|
||||
1. At this point, you can finally install Nextcloud AIO on a new server/linux installation, enter your domain (use the same domain that you used on your former installation) and wait until all containers are running
|
||||
1. At this point, you can finally install Nextcloud AIO on a new server/linux installation, enter your domain in the AIO interface (use the same domain that you used on your former installation) and wait until all containers are running. Then you should check the included Nextcloud version by running `sudo docker inspect nextcloud-aio-nextcloud | grep NEXTCLOUD_VERSION`.
|
||||
1. Next, take a backup using Nextcloud AIO's built-in backup solution (so that you can easily restore to this state again) (Note: this will stop all containers and is expected: don't start the container again at this point!)
|
||||
1. Now, we are slowly starting to import your files and database. First, you need to modify the datadirectory that is stored inside the database export:
|
||||
1. Find out what the directory of your old Nextcloud installation is by e.g. opening the config.php file and looking at the value `datadirectory`.
|
||||
@@ -73,7 +73,7 @@ The procedure for migrating the files and the database works like this:
|
||||
sudo rm -r /var/lib/docker/volumes/nextcloud_aio_database/_data/*
|
||||
```
|
||||
1. If the commands above were executed successfully, restore the datadirectory of your former instance into the following directory: `/var/lib/docker/volumes/nextcloud_aio_nextcloud_data/_data/`
|
||||
1. Next, run `sudo chown -R 33:0 /var/lib/docker/volumes/nextcloud_aio_nextcloud_data/_data/*` to apply the correct permissions
|
||||
1. Next, run `sudo chown -R 33:0 /var/lib/docker/volumes/nextcloud_aio_nextcloud_data/_data/*` and `sudo chmod -R 750 /var/lib/docker/volumes/nextcloud_aio_nextcloud_data/_data/*`to apply the correct permissions
|
||||
1. Edit the Nextcloud AIO config.php file that is stored in `/var/lib/docker/volumes/nextcloud_aio_nextcloud/_data/config/config.php` and modify only `passwordsalt`, `secret`, `instanceid` and set it to the old values that you used on your old installation. If you are brave, feel free to modify further values e.g. add your old LDAP config or S3 storage config. (Some things like Mail server config can be added back using Nextcloud's webinterface later on).
|
||||
1. When you are done and saved your changes to the file, finally start the containers again and wait until all containers are running.
|
||||
1. Now run `sudo docker exec -it nextcloud-aio-nextcloud php occ maintenance:data-fingerprint`.
|
||||
|
||||
@@ -12,10 +12,15 @@
|
||||
"slim/slim": "4.*",
|
||||
"php-di/slim-bridge": "^3.1",
|
||||
"guzzlehttp/guzzle": "^7.3",
|
||||
"guzzlehttp/psr7": "^1.8",
|
||||
"guzzlehttp/psr7": "^2.1.0",
|
||||
"http-interop/http-factory-guzzle": "^1.2",
|
||||
"slim/twig-view": "^3.2",
|
||||
"slim/csrf": "^1.2",
|
||||
"ext-apcu": "*"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"psalm": "psalm --threads=1",
|
||||
"psalm:update-baseline": "psalm --threads=1 --update-baseline",
|
||||
"lint": "find . -name \\*.php -not -path './vendor/*' -print0 | xargs -0 -n1 php -l"
|
||||
}
|
||||
}
|
||||
|
||||
701
php/composer.lock
generated
701
php/composer.lock
generated
File diff suppressed because it is too large
Load Diff
79
php/containers-schema.json
Normal file
79
php/containers-schema.json
Normal file
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"type": "object",
|
||||
"description": "AIO containers definition schema",
|
||||
"additionalProperties": false,
|
||||
"minProperties": 1,
|
||||
"properties": {
|
||||
"production": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"minProperties": 11,
|
||||
"properties": {
|
||||
"containerName": {
|
||||
"type": "string"
|
||||
},
|
||||
"dependsOn": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"displayName": {
|
||||
"type": "string"
|
||||
},
|
||||
"environmentVariables": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"identifier": {
|
||||
"type": "string"
|
||||
},
|
||||
"internalPorts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"maxShutdownTime": {
|
||||
"type": "integer"
|
||||
},
|
||||
"ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"restartPolicy": {
|
||||
"type": "string"
|
||||
},
|
||||
"secrets": {
|
||||
"type": "array"
|
||||
},
|
||||
"volumes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"minProperties": 3,
|
||||
"properties": {
|
||||
"location": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"writeable": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,31 @@
|
||||
{
|
||||
"production": [
|
||||
{
|
||||
"dependsOn": [
|
||||
"nextcloud-aio-nextcloud",
|
||||
"nextcloud-aio-collabora",
|
||||
"nextcloud-aio-talk"
|
||||
],
|
||||
"identifier": "nextcloud-aio-apache",
|
||||
"dependsOn": [
|
||||
"nextcloud-aio-onlyoffice",
|
||||
"nextcloud-aio-collabora",
|
||||
"nextcloud-aio-clamav",
|
||||
"nextcloud-aio-talk",
|
||||
"nextcloud-aio-nextcloud"
|
||||
],
|
||||
"displayName": "Apache",
|
||||
"containerName": "nextcloud/aio-apache",
|
||||
"ports": [
|
||||
"443/tcp"
|
||||
"%APACHE_PORT%/tcp"
|
||||
],
|
||||
"internalPorts": [
|
||||
"443"
|
||||
"%APACHE_PORT%"
|
||||
],
|
||||
"secrets": [],
|
||||
"environmentVariables": [
|
||||
"NC_DOMAIN=%NC_DOMAIN%",
|
||||
"NEXTCLOUD_HOST=nextcloud-aio-nextcloud",
|
||||
"COLLABORA_HOST=nextcloud-aio-collabora",
|
||||
"TALK_HOST=nextcloud-aio-talk"
|
||||
"TALK_HOST=nextcloud-aio-talk",
|
||||
"APACHE_PORT=%APACHE_PORT%",
|
||||
"ONLYOFFICE_HOST=nextcloud-aio-onlyoffice",
|
||||
"TZ=%TIMEZONE%"
|
||||
],
|
||||
"volumes": [
|
||||
{
|
||||
@@ -38,8 +43,8 @@
|
||||
"restartPolicy": "unless-stopped"
|
||||
},
|
||||
{
|
||||
"dependsOn": [],
|
||||
"identifier": "nextcloud-aio-database",
|
||||
"dependsOn": [],
|
||||
"displayName": "Database",
|
||||
"containerName": "nextcloud/aio-postgresql",
|
||||
"ports": [],
|
||||
@@ -64,17 +69,19 @@
|
||||
"environmentVariables": [
|
||||
"POSTGRES_PASSWORD=%DATABASE_PASSWORD%",
|
||||
"POSTGRES_DB=nextcloud_database",
|
||||
"POSTGRES_USER=nextcloud"
|
||||
"POSTGRES_USER=nextcloud",
|
||||
"TZ=%TIMEZONE%",
|
||||
"PGTZ=%TIMEZONE%"
|
||||
],
|
||||
"maxShutdownTime": 1800,
|
||||
"restartPolicy": "unless-stopped"
|
||||
},
|
||||
{
|
||||
"identifier": "nextcloud-aio-nextcloud",
|
||||
"dependsOn": [
|
||||
"nextcloud-aio-database",
|
||||
"nextcloud-aio-redis"
|
||||
],
|
||||
"identifier": "nextcloud-aio-nextcloud",
|
||||
"displayName": "Nextcloud",
|
||||
"containerName": "nextcloud/aio-nextcloud",
|
||||
"ports": [],
|
||||
@@ -95,9 +102,14 @@
|
||||
"writeable": true
|
||||
},
|
||||
{
|
||||
"name": "nextcloud_aio_nextcloud_data",
|
||||
"name": "%NEXTCLOUD_DATADIR%",
|
||||
"location": "/mnt/ncdata",
|
||||
"writeable": true
|
||||
},
|
||||
{
|
||||
"name": "%NEXTCLOUD_MOUNT%",
|
||||
"location": "%NEXTCLOUD_MOUNT%",
|
||||
"writeable": true
|
||||
}
|
||||
],
|
||||
"environmentVariables": [
|
||||
@@ -114,17 +126,28 @@
|
||||
"NEXTCLOUD_DATA_DIR=/mnt/ncdata",
|
||||
"OVERWRITEHOST=%NC_DOMAIN%",
|
||||
"OVERWRITEPROTOCOL=https",
|
||||
"TRUSTED_PROXIES=127.0.0.1",
|
||||
"TURN_SECRET=%TURN_SECRET%",
|
||||
"SIGNALING_SECRET=%SIGNALING_SECRET%",
|
||||
"AIO_URL=%AIO_URL%"
|
||||
"ONLYOFFICE_SECRET=%ONLYOFFICE_SECRET%",
|
||||
"AIO_URL=%AIO_URL%",
|
||||
"NEXTCLOUD_MOUNT=%NEXTCLOUD_MOUNT%",
|
||||
"CLAMAV_ENABLED=%CLAMAV_ENABLED%",
|
||||
"CLAMAV_HOST=nextcloud-aio-clamav",
|
||||
"ONLYOFFICE_ENABLED=%ONLYOFFICE_ENABLED%",
|
||||
"COLLABORA_ENABLED=%COLLABORA_ENABLED%",
|
||||
"COLLABORA_HOST=nextcloud-aio-collabora",
|
||||
"TALK_ENABLED=%TALK_ENABLED%",
|
||||
"ONLYOFFICE_HOST=nextcloud-aio-onlyoffice",
|
||||
"UPDATE_NEXTCLOUD_APPS=%UPDATE_NEXTCLOUD_APPS%",
|
||||
"TZ=%TIMEZONE%",
|
||||
"TALK_PORT=%TALK_PORT%"
|
||||
],
|
||||
"maxShutdownTime": 10,
|
||||
"restartPolicy": "unless-stopped"
|
||||
},
|
||||
{
|
||||
"dependsOn": [],
|
||||
"identifier": "nextcloud-aio-redis",
|
||||
"dependsOn": [],
|
||||
"displayName": "Redis",
|
||||
"containerName": "nextcloud/aio-redis",
|
||||
"ports": [],
|
||||
@@ -132,18 +155,20 @@
|
||||
"6379"
|
||||
],
|
||||
"environmentVariables": [
|
||||
"REDIS_HOST_PASSWORD=%REDIS_PASSWORD%"
|
||||
"REDIS_HOST_PASSWORD=%REDIS_PASSWORD%",
|
||||
"TZ=%TIMEZONE%"
|
||||
],
|
||||
"volumes": [],
|
||||
"secrets": [
|
||||
"REDIS_PASSWORD"
|
||||
"REDIS_PASSWORD",
|
||||
"ONLYOFFICE_SECRET"
|
||||
],
|
||||
"maxShutdownTime": 10,
|
||||
"restartPolicy": "unless-stopped"
|
||||
},
|
||||
{
|
||||
"dependsOn": [],
|
||||
"identifier": "nextcloud-aio-collabora",
|
||||
"dependsOn": [],
|
||||
"displayName": "Collabora",
|
||||
"containerName": "nextcloud/aio-collabora",
|
||||
"ports": [],
|
||||
@@ -151,7 +176,10 @@
|
||||
"9980"
|
||||
],
|
||||
"environmentVariables": [
|
||||
"domain=%NC_DOMAIN%"
|
||||
"aliasgroup1=https://%NC_DOMAIN%:443",
|
||||
"extra_params=--o:ssl.enable=false --o:ssl.termination=true --o:logging.level=warning",
|
||||
"dictionaries=%COLLABORA_DICTIONARIES%",
|
||||
"TZ=%TIMEZONE%"
|
||||
],
|
||||
"volumes": [],
|
||||
"secrets": [],
|
||||
@@ -159,22 +187,24 @@
|
||||
"restartPolicy": "unless-stopped"
|
||||
},
|
||||
{
|
||||
"dependsOn": [],
|
||||
"identifier": "nextcloud-aio-talk",
|
||||
"dependsOn": [],
|
||||
"displayName": "Talk",
|
||||
"containerName": "nextcloud/aio-talk",
|
||||
"ports": [
|
||||
"3478/tcp",
|
||||
"3478/udp"
|
||||
"%TALK_PORT%/tcp",
|
||||
"%TALK_PORT%/udp"
|
||||
],
|
||||
"internalPorts": [
|
||||
"3478"
|
||||
"%TALK_PORT%"
|
||||
],
|
||||
"environmentVariables": [
|
||||
"NC_DOMAIN=%NC_DOMAIN%",
|
||||
"TURN_SECRET=%TURN_SECRET%",
|
||||
"SIGNALING_SECRET=%SIGNALING_SECRET%",
|
||||
"JANUS_API_KEY=%JANUS_API_KEY%"
|
||||
"JANUS_API_KEY=%JANUS_API_KEY%",
|
||||
"TZ=%TIMEZONE%",
|
||||
"TALK_PORT=%TALK_PORT%"
|
||||
],
|
||||
"volumes": [],
|
||||
"secrets": [
|
||||
@@ -186,15 +216,17 @@
|
||||
"restartPolicy": "unless-stopped"
|
||||
},
|
||||
{
|
||||
"dependsOn": [],
|
||||
"identifier": "nextcloud-aio-borgbackup",
|
||||
"dependsOn": [],
|
||||
"displayName": "Borgbackup",
|
||||
"containerName": "nextcloud/aio-borgbackup",
|
||||
"ports": [],
|
||||
"internalPorts": [],
|
||||
"environmentVariables": [
|
||||
"BORG_PASSWORD=%BORGBACKUP_PASSWORD%",
|
||||
"BORG_MODE=%BORGBACKUP_MODE%"
|
||||
"BORG_MODE=%BORGBACKUP_MODE%",
|
||||
"SELECTED_RESTORE_TIME=%SELECTED_RESTORE_TIME%",
|
||||
"BACKUP_RESTORE_PASSWORD=%BACKUP_RESTORE_PASSWORD%"
|
||||
],
|
||||
"volumes": [
|
||||
{
|
||||
@@ -208,7 +240,7 @@
|
||||
"writeable": true
|
||||
},
|
||||
{
|
||||
"name": "nextcloud_aio_nextcloud_data",
|
||||
"name": "%NEXTCLOUD_DATADIR%",
|
||||
"location": "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data",
|
||||
"writeable": true
|
||||
},
|
||||
@@ -245,8 +277,8 @@
|
||||
"restartPolicy": ""
|
||||
},
|
||||
{
|
||||
"dependsOn": [],
|
||||
"identifier": "nextcloud-aio-watchtower",
|
||||
"dependsOn": [],
|
||||
"displayName": "Watchtower",
|
||||
"containerName": "nextcloud/aio-watchtower",
|
||||
"ports": [],
|
||||
@@ -256,7 +288,7 @@
|
||||
],
|
||||
"volumes": [
|
||||
{
|
||||
"name": "/var/run/docker.sock",
|
||||
"name": "%DOCKER_SOCKET_PATH%",
|
||||
"location": "/var/run/docker.sock",
|
||||
"writeable": false
|
||||
}
|
||||
@@ -271,11 +303,12 @@
|
||||
"displayName": "Domaincheck",
|
||||
"containerName": "nextcloud/aio-domaincheck",
|
||||
"ports": [
|
||||
"443/tcp"
|
||||
"%APACHE_PORT%/tcp"
|
||||
],
|
||||
"internalPorts": [],
|
||||
"environmentVariables": [
|
||||
"INSTANCE_ID=%INSTANCE_ID%"
|
||||
"INSTANCE_ID=%INSTANCE_ID%",
|
||||
"APACHE_PORT=%APACHE_PORT%"
|
||||
],
|
||||
"volumes": [],
|
||||
"secrets": [
|
||||
@@ -283,6 +316,57 @@
|
||||
],
|
||||
"maxShutdownTime": 1,
|
||||
"restartPolicy": ""
|
||||
},
|
||||
{
|
||||
"identifier": "nextcloud-aio-clamav",
|
||||
"dependsOn": [],
|
||||
"displayName": "ClamAV",
|
||||
"containerName": "nextcloud/aio-clamav",
|
||||
"ports": [],
|
||||
"internalPorts": [
|
||||
"3310"
|
||||
],
|
||||
"environmentVariables": [
|
||||
"TZ=%TIMEZONE%"
|
||||
],
|
||||
"volumes": [
|
||||
{
|
||||
"name": "nextcloud_aio_clamav",
|
||||
"location": "/var/lib/clamav",
|
||||
"writeable": true
|
||||
}
|
||||
],
|
||||
"secrets": [],
|
||||
"maxShutdownTime": 10,
|
||||
"restartPolicy": "unless-stopped"
|
||||
},
|
||||
{
|
||||
"identifier": "nextcloud-aio-onlyoffice",
|
||||
"dependsOn": [],
|
||||
"displayName": "OnlyOffice",
|
||||
"containerName": "nextcloud/aio-onlyoffice",
|
||||
"ports": [],
|
||||
"internalPorts": [
|
||||
"80"
|
||||
],
|
||||
"environmentVariables": [
|
||||
"TZ=%TIMEZONE%",
|
||||
"JWT_ENABLED=true",
|
||||
"JWT_HEADER=AuthorizationJwt",
|
||||
"JWT_SECRET=%ONLYOFFICE_SECRET%"
|
||||
],
|
||||
"volumes": [
|
||||
{
|
||||
"name": "nextcloud_aio_onlyoffice",
|
||||
"location": "/var/lib/onlyoffice",
|
||||
"writeable": true
|
||||
}
|
||||
],
|
||||
"secrets": [
|
||||
"ONLYOFFICE_SECRET"
|
||||
],
|
||||
"maxShutdownTime": 10,
|
||||
"restartPolicy": "unless-stopped"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
77
php/psalm-baseline.xml
Normal file
77
php/psalm-baseline.xml
Normal file
@@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<files psalm-version="4.24.0@06dd975cb55d36af80f242561738f16c5f58264f">
|
||||
<file src="public/index.php">
|
||||
<MissingClosureParamType occurrences="10">
|
||||
<code>$args</code>
|
||||
<code>$args</code>
|
||||
<code>$args</code>
|
||||
<code>$args</code>
|
||||
<code>$request</code>
|
||||
<code>$request</code>
|
||||
<code>$request</code>
|
||||
<code>$response</code>
|
||||
<code>$response</code>
|
||||
<code>$response</code>
|
||||
</MissingClosureParamType>
|
||||
</file>
|
||||
<file src="src/Controller/ConfigurationController.php">
|
||||
<MissingParamType occurrences="1">
|
||||
<code>$args</code>
|
||||
</MissingParamType>
|
||||
</file>
|
||||
<file src="src/Controller/DockerController.php">
|
||||
<MissingParamType occurrences="8">
|
||||
<code>$args</code>
|
||||
<code>$args</code>
|
||||
<code>$args</code>
|
||||
<code>$args</code>
|
||||
<code>$args</code>
|
||||
<code>$args</code>
|
||||
<code>$args</code>
|
||||
<code>$args</code>
|
||||
</MissingParamType>
|
||||
<PossiblyInvalidArrayAccess occurrences="1">
|
||||
<code>$request->getParsedBody()['selected_restore_time']</code>
|
||||
</PossiblyInvalidArrayAccess>
|
||||
<PossiblyNullArrayAccess occurrences="1">
|
||||
<code>$request->getParsedBody()['selected_restore_time']</code>
|
||||
</PossiblyNullArrayAccess>
|
||||
</file>
|
||||
<file src="src/Controller/LoginController.php">
|
||||
<MissingParamType occurrences="3">
|
||||
<code>$args</code>
|
||||
<code>$args</code>
|
||||
<code>$args</code>
|
||||
</MissingParamType>
|
||||
<PossiblyInvalidArrayAccess occurrences="1">
|
||||
<code>$request->getParsedBody()['password']</code>
|
||||
</PossiblyInvalidArrayAccess>
|
||||
<PossiblyNullArgument occurrences="1">
|
||||
<code>$password</code>
|
||||
</PossiblyNullArgument>
|
||||
<PossiblyNullArrayAccess occurrences="1">
|
||||
<code>$request->getParsedBody()['password']</code>
|
||||
</PossiblyNullArrayAccess>
|
||||
</file>
|
||||
<file src="src/Docker/DockerActionManager.php">
|
||||
<InvalidReturnType occurrences="1">
|
||||
<code>IContainerState</code>
|
||||
</InvalidReturnType>
|
||||
<InvalidScalarArgument occurrences="1">
|
||||
<code>$internalPort</code>
|
||||
</InvalidScalarArgument>
|
||||
<RedundantCondition occurrences="1">
|
||||
<code>$container->GetInternalPorts() !== null</code>
|
||||
</RedundantCondition>
|
||||
</file>
|
||||
<file src="src/Middleware/AuthMiddleware.php">
|
||||
<UndefinedInterfaceMethod occurrences="1">
|
||||
<code>withStatus</code>
|
||||
</UndefinedInterfaceMethod>
|
||||
</file>
|
||||
<file src="src/Twig/ClassExtension.php">
|
||||
<MissingParamType occurrences="1">
|
||||
<code>$object</code>
|
||||
</MissingParamType>
|
||||
</file>
|
||||
</files>
|
||||
15
php/psalm.xml
Normal file
15
php/psalm.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0"?>
|
||||
<psalm
|
||||
errorLevel="2"
|
||||
resolveFromConfigFile="true"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="https://getpsalm.org/schema/config"
|
||||
xsi:schemaLocation="https://getpsalm.org/schema/config"
|
||||
errorBaseline="psalm-baseline.xml"
|
||||
>
|
||||
<projectFiles>
|
||||
<directory name="templates"/>
|
||||
<directory name="src"/>
|
||||
<file name="public/index.php"/>
|
||||
</projectFiles>
|
||||
</psalm>
|
||||
17
php/public/automatic_reload.js
Normal file
17
php/public/automatic_reload.js
Normal file
@@ -0,0 +1,17 @@
|
||||
if (document.hasFocus()) {
|
||||
// hide reload button if the site reloads automatically
|
||||
var list = document.getElementsByClassName("reload button");
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
// list[i] is a node with the desired class name
|
||||
list[i].style.display = 'none';
|
||||
}
|
||||
|
||||
// set timeout for reload
|
||||
setTimeout(function(){
|
||||
window.location.reload(1);
|
||||
}, 5000);
|
||||
} else {
|
||||
window.addEventListener("beforeunload", function() {
|
||||
document.getElementById('overlay').classList.add('loading')
|
||||
});
|
||||
}
|
||||
3
php/public/before-unload.js
Normal file
3
php/public/before-unload.js
Normal file
@@ -0,0 +1,3 @@
|
||||
window.addEventListener("beforeunload", function() {
|
||||
document.getElementById('overlay').classList.add('loading')
|
||||
});
|
||||
5
php/public/disable-clamav.js
Normal file
5
php/public/disable-clamav.js
Normal file
@@ -0,0 +1,5 @@
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
// Clamav
|
||||
var clamav = document.getElementById("clamav");
|
||||
clamav.disabled = true;
|
||||
});
|
||||
5
php/public/disable-collabora.js
Normal file
5
php/public/disable-collabora.js
Normal file
@@ -0,0 +1,5 @@
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
// Collabora
|
||||
var collabora = document.getElementById("collabora");
|
||||
collabora.disabled = true;
|
||||
});
|
||||
5
php/public/disable-onlyoffice.js
Normal file
5
php/public/disable-onlyoffice.js
Normal file
@@ -0,0 +1,5 @@
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
// OnlyOffice
|
||||
var onlyoffice = document.getElementById("onlyoffice");
|
||||
onlyoffice.disabled = true;
|
||||
});
|
||||
5
php/public/disable-talk.js
Normal file
5
php/public/disable-talk.js
Normal file
@@ -0,0 +1,5 @@
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
// Talk
|
||||
var talk = document.getElementById("talk");
|
||||
talk.disabled = true;
|
||||
});
|
||||
@@ -12,7 +12,7 @@
|
||||
}
|
||||
lastError = toast
|
||||
body.prepend(toast)
|
||||
setTimeout(toast.remove.bind(toast), 3000)
|
||||
setTimeout(toast.remove.bind(toast), 10000)
|
||||
}
|
||||
|
||||
function handleEvent(e) {
|
||||
|
||||
@@ -22,11 +22,6 @@ ini_set('session.save_path', $dataConst->GetSessionDirectory());
|
||||
// Auto logout on browser close
|
||||
ini_set('session.cookie_lifetime', '0');
|
||||
|
||||
// Make sure to delete all stale sessions after at least one day
|
||||
ini_set('session.gc_maxlifetime', '86400');
|
||||
ini_set('session.gc_probability', '1');
|
||||
ini_set('session.gc_divisor', '1');
|
||||
|
||||
// Create app
|
||||
AppFactory::setContainer($container);
|
||||
$app = AppFactory::create();
|
||||
@@ -53,9 +48,11 @@ $app->add(new \AIO\Middleware\AuthMiddleware($container->get(\AIO\Auth\AuthManag
|
||||
|
||||
// API
|
||||
$app->post('/api/docker/watchtower', AIO\Controller\DockerController::class . ':StartWatchtowerContainer');
|
||||
$app->get('/api/docker/getwatchtower', AIO\Controller\DockerController::class . ':StartWatchtowerContainer');
|
||||
$app->post('/api/docker/start', AIO\Controller\DockerController::class . ':StartContainer');
|
||||
$app->post('/api/docker/backup', AIO\Controller\DockerController::class . ':StartBackupContainerBackup');
|
||||
$app->post('/api/docker/backup-check', AIO\Controller\DockerController::class . ':StartBackupContainerCheck');
|
||||
$app->post('/api/docker/backup-test', AIO\Controller\DockerController::class . ':StartBackupContainerTest');
|
||||
$app->post('/api/docker/restore', AIO\Controller\DockerController::class . ':StartBackupContainerRestore');
|
||||
$app->post('/api/docker/stop', AIO\Controller\DockerController::class . ':StopContainer');
|
||||
$app->get('/api/docker/logs', AIO\Controller\DockerController::class . ':GetLogs');
|
||||
@@ -77,16 +74,33 @@ $app->get('/containers', function ($request, $response, $args) use ($container)
|
||||
return $view->render($response, 'containers.twig', [
|
||||
'domain' => $configurationManager->GetDomain(),
|
||||
'borg_backup_host_location' => $configurationManager->GetBorgBackupHostLocation(),
|
||||
'borg_backup_mode' => $configurationManager->GetBorgBackupMode(),
|
||||
'nextcloud_password' => $configurationManager->GetSecret('NEXTCLOUD_PASSWORD'),
|
||||
'containers' => (new \AIO\ContainerDefinitionFetcher($container->get(\AIO\Data\ConfigurationManager::class), $container))->FetchDefinition(),
|
||||
'borgbackup_password' => $configurationManager->GetSecret('BORGBACKUP_PASSWORD'),
|
||||
'is_mastercontainer_update_available' => $dockerActionManger->IsMastercontainerUpdateAvailable(),
|
||||
'has_backup_run_once' => $configurationManager->hasBackupRunOnce(),
|
||||
'is_backup_container_running' => $dockerActionManger->isBackupContainerRunning(),
|
||||
'backup_exit_code' => $dockerActionManger->GetBackupcontainerExitCode(),
|
||||
'is_instance_restore_attempt' => $configurationManager->isInstanceRestoreAttempt(),
|
||||
'borg_backup_mode' => $configurationManager->GetBorgBackupMode(),
|
||||
'was_start_button_clicked' => $configurationManager->wasStartButtonClicked(),
|
||||
'has_update_available' => $dockerActionManger->isAnyUpdateAvailable(),
|
||||
'last_backup_time' => $configurationManager->GetLastBackupTime(),
|
||||
'backup_times' => $configurationManager->GetBackupTimes(),
|
||||
'current_channel' => $dockerActionManger->GetCurrentChannel(),
|
||||
'is_x64_platform' => $configurationManager->isx64Platform(),
|
||||
'is_clamav_enabled' => $configurationManager->isClamavEnabled(),
|
||||
'is_onlyoffice_enabled' => $configurationManager->isOnlyofficeEnabled(),
|
||||
'is_collabora_enabled' => $configurationManager->isCollaboraEnabled(),
|
||||
'is_talk_enabled' => $configurationManager->isTalkEnabled(),
|
||||
'borg_restore_password' => $configurationManager->GetBorgRestorePassword(),
|
||||
'daily_backup_time' => $configurationManager->GetDailyBackupTime(),
|
||||
'is_daily_backup_running' => $configurationManager->isDailyBackupRunning(),
|
||||
'timezone' => $configurationManager->GetTimezone(),
|
||||
'skip_domain_validation' => $configurationManager->shouldDomainValidationBeSkipped(),
|
||||
'talk_port' => $configurationManager->GetTalkPort(),
|
||||
'collabora_dictionaries' => $configurationManager->GetCollaboraDictionaries(),
|
||||
'automatic_updates' => $configurationManager->areAutomaticUpdatesEnabled(),
|
||||
]);
|
||||
})->setName('profile');
|
||||
$app->get('/login', function ($request, $response, $args) use ($container) {
|
||||
@@ -141,4 +155,6 @@ $app->get('/', function (\Psr\Http\Message\RequestInterface $request, \Psr\Http\
|
||||
}
|
||||
});
|
||||
|
||||
$errorMiddleware = $app->addErrorMiddleware(true, true, true);
|
||||
|
||||
$app->run();
|
||||
|
||||
26
php/public/options-form-submit.js
Normal file
26
php/public/options-form-submit.js
Normal file
@@ -0,0 +1,26 @@
|
||||
function makeOptionsFormSubmitVisible() {
|
||||
var optionsFormSubmit = document.getElementById("options-form-submit");
|
||||
optionsFormSubmit.style.display = 'block';
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
// handle submit button for options form
|
||||
var optionsFormSubmit = document.getElementById("options-form-submit");
|
||||
optionsFormSubmit.style.display = 'none';
|
||||
|
||||
// Clamav
|
||||
var clamav = document.getElementById("clamav");
|
||||
clamav.addEventListener('change', makeOptionsFormSubmitVisible);
|
||||
|
||||
// OnlyOffice
|
||||
var onlyoffice = document.getElementById("onlyoffice");
|
||||
onlyoffice.addEventListener('change', makeOptionsFormSubmitVisible);
|
||||
|
||||
// Collabora
|
||||
var collabora = document.getElementById("collabora");
|
||||
collabora.addEventListener('change', makeOptionsFormSubmitVisible);
|
||||
|
||||
// Talk
|
||||
var talk = document.getElementById("talk");
|
||||
talk.addEventListener('change', makeOptionsFormSubmitVisible);
|
||||
});
|
||||
@@ -23,6 +23,10 @@ a {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
summary {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
@@ -136,7 +140,7 @@ input {
|
||||
padding: 20px;
|
||||
max-width: 100%;
|
||||
word-break: break-word;
|
||||
max-width: 450px;
|
||||
max-width: 470px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
|
||||
@@ -7792,7 +7792,7 @@ class PasswordGenerator
|
||||
if($password !== '') {
|
||||
$password = $password . ' ';
|
||||
}
|
||||
$password = $password . $this->words[random_int(0, 2047)];
|
||||
$password = $password . $this->words[random_int(0, 7775)];
|
||||
}
|
||||
|
||||
return $password;
|
||||
|
||||
@@ -91,6 +91,10 @@ class Container {
|
||||
return $this->dockerActionManager->GetContainerRunningState($this);
|
||||
}
|
||||
|
||||
public function GetRestartingState() : IContainerState {
|
||||
return $this->dockerActionManager->GetContainerRestartingState($this);
|
||||
}
|
||||
|
||||
public function GetUpdateState() : IContainerState {
|
||||
return $this->dockerActionManager->GetContainerUpdateState($this);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ class ContainerVolumes {
|
||||
/** @var ContainerVolume[] */
|
||||
private array $volumes = [];
|
||||
|
||||
public function AddVolume(ContainerVolume $volume) {
|
||||
public function AddVolume(ContainerVolume $volume) : void {
|
||||
$this->volumes[] = $volume;
|
||||
}
|
||||
|
||||
|
||||
6
php/src/Container/State/NotRestartingState.php
Normal file
6
php/src/Container/State/NotRestartingState.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace AIO\Container\State;
|
||||
|
||||
class NotRestartingState implements IContainerState
|
||||
{}
|
||||
6
php/src/Container/State/RestartingState.php
Normal file
6
php/src/Container/State/RestartingState.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace AIO\Container\State;
|
||||
|
||||
class RestartingState implements IContainerState
|
||||
{}
|
||||
@@ -27,7 +27,7 @@ class ContainerDefinitionFetcher
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
public function GetContainerById(string $id): ?Container
|
||||
public function GetContainerById(string $id): Container
|
||||
{
|
||||
$containers = $this->FetchDefinition();
|
||||
|
||||
@@ -37,7 +37,7 @@ class ContainerDefinitionFetcher
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
throw new \Exception("The provided id " . $id . " was not found in the container definition.");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,13 +49,43 @@ class ContainerDefinitionFetcher
|
||||
|
||||
$containers = [];
|
||||
foreach ($data['production'] as $entry) {
|
||||
if ($entry['identifier'] === 'nextcloud-aio-clamav') {
|
||||
if (!$this->configurationManager->isClamavEnabled()) {
|
||||
continue;
|
||||
}
|
||||
} elseif ($entry['identifier'] === 'nextcloud-aio-onlyoffice') {
|
||||
if (!$this->configurationManager->isOnlyofficeEnabled()) {
|
||||
continue;
|
||||
}
|
||||
} elseif ($entry['identifier'] === 'nextcloud-aio-collabora') {
|
||||
if (!$this->configurationManager->isCollaboraEnabled()) {
|
||||
continue;
|
||||
}
|
||||
} elseif ($entry['identifier'] === 'nextcloud-aio-talk') {
|
||||
if (!$this->configurationManager->isTalkEnabled()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$ports = new ContainerPorts();
|
||||
foreach ($entry['ports'] as $port) {
|
||||
if($port === '%APACHE_PORT%/tcp') {
|
||||
$port = $this->configurationManager->GetApachePort() . '/tcp';
|
||||
} elseif($port === '%TALK_PORT%/tcp') {
|
||||
$port = $this->configurationManager->GetTalkPort() . '/tcp';
|
||||
} elseif($port === '%TALK_PORT%/udp') {
|
||||
$port = $this->configurationManager->GetTalkPort() . '/udp';
|
||||
}
|
||||
$ports->AddPort($port);
|
||||
}
|
||||
|
||||
$internalPorts = new ContainerInternalPorts();
|
||||
foreach ($entry['internalPorts'] as $internalPort) {
|
||||
if($internalPort === '%APACHE_PORT%') {
|
||||
$internalPort = $this->configurationManager->GetApachePort();
|
||||
} elseif($internalPort === '%TALK_PORT%') {
|
||||
$internalPort = $this->configurationManager->GetTalkPort();
|
||||
}
|
||||
$internalPorts->AddInternalPort($internalPort);
|
||||
}
|
||||
|
||||
@@ -67,6 +97,28 @@ class ContainerDefinitionFetcher
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if($value['name'] === '%NEXTCLOUD_MOUNT%') {
|
||||
$value['name'] = $this->configurationManager->GetNextcloudMount();
|
||||
if($value['name'] === '') {
|
||||
continue;
|
||||
}
|
||||
} elseif ($value['name'] === '%NEXTCLOUD_DATADIR%') {
|
||||
$value['name'] = $this->configurationManager->GetNextcloudDatadirMount();
|
||||
if ($value['name'] === '') {
|
||||
continue;
|
||||
}
|
||||
} elseif ($value['name'] === '%DOCKER_SOCKET_PATH%') {
|
||||
$value['name'] = $this->configurationManager->GetDockerSocketPath();
|
||||
if($value['name'] === '') {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ($value['location'] === '%NEXTCLOUD_MOUNT%') {
|
||||
$value['location'] = $this->configurationManager->GetNextcloudMount();
|
||||
if($value['location'] === '') {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$volumes->AddVolume(
|
||||
new ContainerVolume(
|
||||
$value['name'],
|
||||
@@ -76,6 +128,28 @@ class ContainerDefinitionFetcher
|
||||
);
|
||||
}
|
||||
|
||||
$dependsOn = [];
|
||||
foreach ($entry['dependsOn'] as $value) {
|
||||
if ($value === 'nextcloud-aio-clamav') {
|
||||
if (!$this->configurationManager->isClamavEnabled()) {
|
||||
continue;
|
||||
}
|
||||
} elseif ($value === 'nextcloud-aio-onlyoffice') {
|
||||
if (!$this->configurationManager->isOnlyofficeEnabled()) {
|
||||
continue;
|
||||
}
|
||||
} elseif ($value === 'nextcloud-aio-collabora') {
|
||||
if (!$this->configurationManager->isCollaboraEnabled()) {
|
||||
continue;
|
||||
}
|
||||
} elseif ($value === 'nextcloud-aio-talk') {
|
||||
if (!$this->configurationManager->isTalkEnabled()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$dependsOn[] = $value;
|
||||
}
|
||||
|
||||
$variables = new ContainerEnvironmentVariables();
|
||||
foreach ($entry['environmentVariables'] as $value) {
|
||||
$variables->AddVariable($value);
|
||||
@@ -91,7 +165,7 @@ class ContainerDefinitionFetcher
|
||||
$internalPorts,
|
||||
$volumes,
|
||||
$variables,
|
||||
$entry['dependsOn'],
|
||||
$dependsOn,
|
||||
$entry['secrets'],
|
||||
$this->container->get(DockerActionManager::class)
|
||||
);
|
||||
|
||||
@@ -22,11 +22,83 @@ class ConfigurationController
|
||||
public function SetConfig(Request $request, Response $response, $args) : Response {
|
||||
try {
|
||||
if (isset($request->getParsedBody()['domain'])) {
|
||||
$this->configurationManager->SetDomain($request->getParsedBody()['domain']);
|
||||
$domain = $request->getParsedBody()['domain'] ?? '';
|
||||
$this->configurationManager->SetDomain($domain);
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['current-master-password']) || isset($request->getParsedBody()['new-master-password'])) {
|
||||
$currentMasterPassword = $request->getParsedBody()['current-master-password'] ?? '';
|
||||
$newMasterPassword = $request->getParsedBody()['new-master-password'] ?? '';
|
||||
$this->configurationManager->ChangeMasterPassword($currentMasterPassword, $newMasterPassword);
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['borg_backup_host_location'])) {
|
||||
$this->configurationManager->SetBorgBackupHostLocation($request->getParsedBody()['borg_backup_host_location']);
|
||||
$location = $request->getParsedBody()['borg_backup_host_location'] ?? '';
|
||||
$this->configurationManager->SetBorgBackupHostLocation($location);
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['borg_restore_host_location']) || isset($request->getParsedBody()['borg_restore_password'])) {
|
||||
$restoreLocation = $request->getParsedBody()['borg_restore_host_location'] ?? '';
|
||||
$borgPassword = $request->getParsedBody()['borg_restore_password'] ?? '';
|
||||
$this->configurationManager->SetBorgRestoreHostLocationAndPassword($restoreLocation, $borgPassword);
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['daily_backup_time'])) {
|
||||
if (isset($request->getParsedBody()['automatic_updates'])) {
|
||||
$enableAutomaticUpdates = true;
|
||||
} else {
|
||||
$enableAutomaticUpdates = false;
|
||||
}
|
||||
$dailyBackupTime = $request->getParsedBody()['daily_backup_time'] ?? '';
|
||||
$this->configurationManager->SetDailyBackupTime($dailyBackupTime, $enableAutomaticUpdates);
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['delete_daily_backup_time'])) {
|
||||
$this->configurationManager->DeleteDailyBackupTime();
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['delete_timezone'])) {
|
||||
$this->configurationManager->DeleteTimezone();
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['timezone'])) {
|
||||
$timezone = $request->getParsedBody()['timezone'] ?? '';
|
||||
$this->configurationManager->SetTimezone($timezone);
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['options-form'])) {
|
||||
if (isset($request->getParsedBody()['collabora']) && isset($request->getParsedBody()['onlyoffice'])) {
|
||||
throw new InvalidSettingConfigurationException("Collabora and Onlyoffice are not allowed to be enabled at the same time!");
|
||||
}
|
||||
if (isset($request->getParsedBody()['clamav'])) {
|
||||
$this->configurationManager->SetClamavEnabledState(1);
|
||||
} else {
|
||||
$this->configurationManager->SetClamavEnabledState(0);
|
||||
}
|
||||
if (isset($request->getParsedBody()['onlyoffice'])) {
|
||||
$this->configurationManager->SetOnlyofficeEnabledState(1);
|
||||
} else {
|
||||
$this->configurationManager->SetOnlyofficeEnabledState(0);
|
||||
}
|
||||
if (isset($request->getParsedBody()['collabora'])) {
|
||||
$this->configurationManager->SetCollaboraEnabledState(1);
|
||||
} else {
|
||||
$this->configurationManager->SetCollaboraEnabledState(0);
|
||||
}
|
||||
if (isset($request->getParsedBody()['talk'])) {
|
||||
$this->configurationManager->SetTalkEnabledState(1);
|
||||
} else {
|
||||
$this->configurationManager->SetTalkEnabledState(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['delete_collabora_dictionaries'])) {
|
||||
$this->configurationManager->DeleteCollaboraDictionaries();
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['collabora_dictionaries'])) {
|
||||
$collaboraDictionaries = $request->getParsedBody()['collabora_dictionaries'] ?? '';
|
||||
$this->configurationManager->SetCollaboraDictionaries($collaboraDictionaries);
|
||||
}
|
||||
|
||||
return $response->withStatus(201)->withHeader('Location', '/');
|
||||
|
||||
@@ -26,16 +26,25 @@ class DockerController
|
||||
$this->configurationManager = $configurationManager;
|
||||
}
|
||||
|
||||
private function PerformRecursiveContainerStart(string $id) {
|
||||
private function PerformRecursiveContainerStart(string $id, bool $pullContainer = true) : void {
|
||||
$container = $this->containerDefinitionFetcher->GetContainerById($id);
|
||||
|
||||
foreach($container->GetDependsOn() as $dependency) {
|
||||
$this->PerformRecursiveContainerStart($dependency);
|
||||
}
|
||||
|
||||
if ($id === 'nextcloud-aio-database') {
|
||||
if ($this->dockerActionManager->GetDatabasecontainerExitCode() > 0) {
|
||||
$pullContainer = false;
|
||||
}
|
||||
}
|
||||
$this->dockerActionManager->DeleteContainer($container);
|
||||
$this->dockerActionManager->CreateVolumes($container);
|
||||
$this->dockerActionManager->PullContainer($container);
|
||||
if ($pullContainer) {
|
||||
$this->dockerActionManager->PullContainer($container);
|
||||
} else {
|
||||
error_log('Not pulling the latest database image because the container was not correctly shut down.');
|
||||
}
|
||||
$this->dockerActionManager->CreateContainer($container);
|
||||
$this->dockerActionManager->StartContainer($container);
|
||||
$this->dockerActionManager->ConnectContainerToNetwork($container);
|
||||
@@ -44,8 +53,12 @@ class DockerController
|
||||
public function GetLogs(Request $request, Response $response, $args) : Response
|
||||
{
|
||||
$id = $request->getQueryParams()['id'];
|
||||
$container = $this->containerDefinitionFetcher->GetContainerById($id);
|
||||
$logs = $this->dockerActionManager->GetLogs($container);
|
||||
if (str_starts_with($id, 'nextcloud-aio-')) {
|
||||
$logs = $this->dockerActionManager->GetLogs($id);
|
||||
} else {
|
||||
$logs = 'Container not found.';
|
||||
}
|
||||
|
||||
$body = $response->getBody();
|
||||
$body->write($logs);
|
||||
|
||||
@@ -56,6 +69,11 @@ class DockerController
|
||||
}
|
||||
|
||||
public function StartBackupContainerBackup(Request $request, Response $response, $args) : Response {
|
||||
$this->startBackup();
|
||||
return $response->withStatus(201)->withHeader('Location', '/');
|
||||
}
|
||||
|
||||
public function startBackup() : void {
|
||||
$config = $this->configurationManager->GetConfig();
|
||||
$config['backup-mode'] = 'backup';
|
||||
$this->configurationManager->WriteConfig($config);
|
||||
@@ -65,8 +83,6 @@ class DockerController
|
||||
|
||||
$id = 'nextcloud-aio-borgbackup';
|
||||
$this->PerformRecursiveContainerStart($id);
|
||||
|
||||
return $response->withStatus(201)->withHeader('Location', '/');
|
||||
}
|
||||
|
||||
public function StartBackupContainerCheck(Request $request, Response $response, $args) : Response {
|
||||
@@ -83,6 +99,22 @@ class DockerController
|
||||
public function StartBackupContainerRestore(Request $request, Response $response, $args) : Response {
|
||||
$config = $this->configurationManager->GetConfig();
|
||||
$config['backup-mode'] = 'restore';
|
||||
$config['selected-restore-time'] = $request->getParsedBody()['selected_restore_time'];
|
||||
$this->configurationManager->WriteConfig($config);
|
||||
|
||||
$id = self::TOP_CONTAINER;
|
||||
$this->PerformRecursiveContainerStop($id);
|
||||
|
||||
$id = 'nextcloud-aio-borgbackup';
|
||||
$this->PerformRecursiveContainerStart($id);
|
||||
|
||||
return $response->withStatus(201)->withHeader('Location', '/');
|
||||
}
|
||||
|
||||
public function StartBackupContainerTest(Request $request, Response $response, $args) : Response {
|
||||
$config = $this->configurationManager->GetConfig();
|
||||
$config['backup-mode'] = 'test';
|
||||
$config['instance_restore_attempt'] = 0;
|
||||
$this->configurationManager->WriteConfig($config);
|
||||
|
||||
$id = self::TOP_CONTAINER;
|
||||
@@ -99,12 +131,26 @@ class DockerController
|
||||
$uri = $request->getUri();
|
||||
$host = $uri->getHost();
|
||||
$port = $uri->getPort();
|
||||
if ($port === 8000) {
|
||||
error_log('The AIO_URL-port was discovered to be 8000 which is not expected. It is now set to 443.');
|
||||
$port = 443;
|
||||
}
|
||||
|
||||
$config = $this->configurationManager->GetConfig();
|
||||
// set AIO_URL
|
||||
$config['AIO_URL'] = $host . ':' . $port;
|
||||
// set wasStartButtonClicked
|
||||
$config['wasStartButtonClicked'] = 1;
|
||||
$this->configurationManager->WriteConfig($config);
|
||||
|
||||
// Start container
|
||||
$this->startTopContainer(true);
|
||||
|
||||
return $response->withStatus(201)->withHeader('Location', '/');
|
||||
}
|
||||
|
||||
public function startTopContainer(bool $pullContainer) : void {
|
||||
$config = $this->configurationManager->GetConfig();
|
||||
// set AIO_TOKEN
|
||||
$config['AIO_TOKEN'] = bin2hex(random_bytes(24));
|
||||
$this->configurationManager->WriteConfig($config);
|
||||
@@ -114,25 +160,29 @@ class DockerController
|
||||
|
||||
$id = self::TOP_CONTAINER;
|
||||
|
||||
$this->PerformRecursiveContainerStart($id);
|
||||
return $response->withStatus(201)->withHeader('Location', '/');
|
||||
$this->PerformRecursiveContainerStart($id, $pullContainer);
|
||||
}
|
||||
|
||||
public function StartWatchtowerContainer(Request $request, Response $response, $args) : Response {
|
||||
$id = 'nextcloud-aio-watchtower';
|
||||
|
||||
$this->PerformRecursiveContainerStart($id);
|
||||
$this->startWatchtower();
|
||||
return $response->withStatus(201)->withHeader('Location', '/');
|
||||
}
|
||||
|
||||
private function PerformRecursiveContainerStop(string $id)
|
||||
public function startWatchtower() : void {
|
||||
$id = 'nextcloud-aio-watchtower';
|
||||
|
||||
$this->PerformRecursiveContainerStart($id);
|
||||
}
|
||||
|
||||
private function PerformRecursiveContainerStop(string $id) : void
|
||||
{
|
||||
$container = $this->containerDefinitionFetcher->GetContainerById($id);
|
||||
foreach($container->GetDependsOn() as $dependency) {
|
||||
$this->PerformRecursiveContainerStop($dependency);
|
||||
}
|
||||
|
||||
$this->dockerActionManager->DisconnectContainerFromNetwork($container);
|
||||
// Disconnecting is not needed. This also allows to start the containers manually via docker-cli
|
||||
//$this->dockerActionManager->DisconnectContainerFromNetwork($container);
|
||||
$this->dockerActionManager->StopContainer($container);
|
||||
}
|
||||
|
||||
@@ -144,28 +194,44 @@ class DockerController
|
||||
return $response->withStatus(201)->withHeader('Location', '/');
|
||||
}
|
||||
|
||||
public function StartDomaincheckContainer()
|
||||
public function stopTopContainer() : void {
|
||||
$id = self::TOP_CONTAINER;
|
||||
$this->PerformRecursiveContainerStop($id);
|
||||
}
|
||||
|
||||
public function StartDomaincheckContainer() : void
|
||||
{
|
||||
# Don't start if domain is already set
|
||||
if ($this->configurationManager->GetDomain() != '') {
|
||||
if ($this->configurationManager->GetDomain() !== '' || $this->configurationManager->wasStartButtonClicked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$id = 'nextcloud-aio-domaincheck';
|
||||
|
||||
$container = $this->containerDefinitionFetcher->GetContainerById($id);
|
||||
// don't start if the domaincheck is already running
|
||||
if ($container->GetIdentifier() === $id && $container->GetRunningState() instanceof RunningState) {
|
||||
return;
|
||||
// don't start if apache is already running
|
||||
} elseif ($container->GetIdentifier() === self::TOP_CONTAINER && $container->GetRunningState() instanceof RunningState) {
|
||||
$cacheKey = 'domaincheckWasStarted';
|
||||
|
||||
$domaincheckContainer = $this->containerDefinitionFetcher->GetContainerById($id);
|
||||
$apacheContainer = $this->containerDefinitionFetcher->GetContainerById(self::TOP_CONTAINER);
|
||||
// Don't start if apache is already running
|
||||
if ($apacheContainer->GetRunningState() instanceof RunningState) {
|
||||
return;
|
||||
// Don't start if domaincheck is already running
|
||||
} elseif ($domaincheckContainer->GetRunningState() instanceof RunningState) {
|
||||
$domaincheckWasStarted = apcu_fetch($cacheKey);
|
||||
// Start domaincheck again when 10 minutes are over by not returning here
|
||||
if($domaincheckWasStarted !== false && is_string($domaincheckWasStarted)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$this->StopDomaincheckContainer();
|
||||
$this->PerformRecursiveContainerStart($id);
|
||||
|
||||
// Cache the start for 10 minutes
|
||||
apcu_add($cacheKey, '1', 600);
|
||||
}
|
||||
|
||||
private function StopDomaincheckContainer()
|
||||
private function StopDomaincheckContainer() : void
|
||||
{
|
||||
$id = 'nextcloud-aio-domaincheck';
|
||||
$this->PerformRecursiveContainerStop($id);
|
||||
|
||||
29
php/src/Cron/BackupNotification.php
Normal file
29
php/src/Cron/BackupNotification.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
// increase memory limit to 2GB
|
||||
ini_set('memory_limit', '2048M');
|
||||
|
||||
use DI\Container;
|
||||
|
||||
require __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
$container = \AIO\DependencyInjection::GetContainer();
|
||||
|
||||
/** @var \AIO\Docker\DockerActionManager $dockerActionManger */
|
||||
$dockerActionManger = $container->get(\AIO\Docker\DockerActionManager::class);
|
||||
/** @var \AIO\ContainerDefinitionFetcher $containerDefinitionFetcher */
|
||||
$containerDefinitionFetcher = $container->get(\AIO\ContainerDefinitionFetcher::class);
|
||||
|
||||
$id = 'nextcloud-aio-nextcloud';
|
||||
$nextcloudContainer = $containerDefinitionFetcher->GetContainerById($id);
|
||||
|
||||
$backupExitCode = $dockerActionManger->GetBackupcontainerExitCode();
|
||||
|
||||
if ($backupExitCode === 0) {
|
||||
$dockerActionManger->sendNotification($nextcloudContainer, 'Daily backup successful!', 'You can get further info by looking at the backup logs in the AIO interface.');
|
||||
}
|
||||
|
||||
if ($backupExitCode > 0) {
|
||||
$dockerActionManger->sendNotification($nextcloudContainer, 'Daily backup failed!', 'You can get further info by looking at the backup logs in the AIO interface.');
|
||||
}
|
||||
17
php/src/Cron/CreateBackup.php
Normal file
17
php/src/Cron/CreateBackup.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
// increase memory limit to 2GB
|
||||
ini_set('memory_limit', '2048M');
|
||||
|
||||
use DI\Container;
|
||||
|
||||
require __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
$container = \AIO\DependencyInjection::GetContainer();
|
||||
|
||||
/** @var \AIO\Controller\DockerController $dockerController */
|
||||
$dockerController = $container->get(\AIO\Controller\DockerController::class);
|
||||
|
||||
// Stop container and start backup
|
||||
$dockerController->startBackup();
|
||||
17
php/src/Cron/StartAndUpdateContainers.php
Normal file
17
php/src/Cron/StartAndUpdateContainers.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
// increase memory limit to 2GB
|
||||
ini_set('memory_limit', '2048M');
|
||||
|
||||
use DI\Container;
|
||||
|
||||
require __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
$container = \AIO\DependencyInjection::GetContainer();
|
||||
|
||||
/** @var \AIO\Controller\DockerController $dockerController */
|
||||
$dockerController = $container->get(\AIO\Controller\DockerController::class);
|
||||
|
||||
// Start apache
|
||||
$dockerController->startTopContainer(true);
|
||||
17
php/src/Cron/StartContainers.php
Normal file
17
php/src/Cron/StartContainers.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
// increase memory limit to 2GB
|
||||
ini_set('memory_limit', '2048M');
|
||||
|
||||
use DI\Container;
|
||||
|
||||
require __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
$container = \AIO\DependencyInjection::GetContainer();
|
||||
|
||||
/** @var \AIO\Controller\DockerController $dockerController */
|
||||
$dockerController = $container->get(\AIO\Controller\DockerController::class);
|
||||
|
||||
// Start apache
|
||||
$dockerController->startTopContainer(false);
|
||||
17
php/src/Cron/StopContainers.php
Normal file
17
php/src/Cron/StopContainers.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
// increase memory limit to 2GB
|
||||
ini_set('memory_limit', '2048M');
|
||||
|
||||
use DI\Container;
|
||||
|
||||
require __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
$container = \AIO\DependencyInjection::GetContainer();
|
||||
|
||||
/** @var \AIO\Controller\DockerController $dockerController */
|
||||
$dockerController = $container->get(\AIO\Controller\DockerController::class);
|
||||
|
||||
// Start apache
|
||||
$dockerController->stopTopContainer();
|
||||
17
php/src/Cron/UpdateMastercontainer.php
Normal file
17
php/src/Cron/UpdateMastercontainer.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
// increase memory limit to 2GB
|
||||
ini_set('memory_limit', '2048M');
|
||||
|
||||
use DI\Container;
|
||||
|
||||
require __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
$container = \AIO\DependencyInjection::GetContainer();
|
||||
|
||||
/** @var \AIO\Controller\DockerController $dockerController */
|
||||
$dockerController = $container->get(\AIO\Controller\DockerController::class);
|
||||
|
||||
# Update the mastercontainer
|
||||
$dockerController->startWatchtower();
|
||||
@@ -22,9 +22,9 @@ $isMastercontainerUpdateAvailable = $dockerActionManger->IsMastercontainerUpdate
|
||||
$isAnyUpdateAvailable = $dockerActionManger->isAnyUpdateAvailable();
|
||||
|
||||
if ($isMastercontainerUpdateAvailable === true) {
|
||||
$dockerActionManger->sendNotification($nextcloudContainer, 'Mastercontainer update available!', 'Please open your management interface to update it.');
|
||||
$dockerActionManger->sendNotification($nextcloudContainer, 'Mastercontainer update available!', 'Please open your AIO interface to update it. If you do not want to do it manually each time, you can enable the daily backup feature from the AIO interface which also automatically updates the mastercontainer.');
|
||||
}
|
||||
|
||||
if ($isAnyUpdateAvailable === true) {
|
||||
$dockerActionManger->sendNotification($nextcloudContainer, 'Container updates available!', 'Please open your management interface to update them.');
|
||||
$dockerActionManger->sendNotification($nextcloudContainer, 'Container updates available!', 'Please open your AIO interface to update them. If you do not want to do it manually each time, you can enable the daily backup feature from the AIO interface which also automatically updates your containers and your Nextcloud apps.');
|
||||
}
|
||||
@@ -46,7 +46,7 @@ class ConfigurationManager
|
||||
return $config['secrets'][$secretId];
|
||||
}
|
||||
|
||||
private function DoubleSafeBackupSecret(string $borgBackupPassword) {
|
||||
private function DoubleSafeBackupSecret(string $borgBackupPassword) : void {
|
||||
file_put_contents(DataConst::GetBackupSecretFile(), $borgBackupPassword);
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ class ConfigurationManager
|
||||
}
|
||||
|
||||
$content = file_get_contents(DataConst::GetBackupArchivesList());
|
||||
if ($content === "") {
|
||||
if ($content === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -83,6 +83,31 @@ class ConfigurationManager
|
||||
return $lastBackupTime;
|
||||
}
|
||||
|
||||
public function GetBackupTimes() : array {
|
||||
if (!file_exists(DataConst::GetBackupArchivesList())) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$content = file_get_contents(DataConst::GetBackupArchivesList());
|
||||
if ($content === '') {
|
||||
return [];
|
||||
}
|
||||
|
||||
$backupLines = explode("\n", $content);
|
||||
$backupTimes = [];
|
||||
foreach($backupLines as $lines) {
|
||||
if ($lines !== "") {
|
||||
$backupTimesTemp = explode(',', $lines);
|
||||
$backupTimes[] = $backupTimesTemp[1];
|
||||
}
|
||||
}
|
||||
|
||||
// Reverse the array to list newest backup first
|
||||
$backupTimes = array_reverse($backupTimes);
|
||||
|
||||
return $backupTimes;
|
||||
}
|
||||
|
||||
public function wasStartButtonClicked() : bool {
|
||||
if (isset($this->GetConfig()['wasStartButtonClicked'])) {
|
||||
return true;
|
||||
@@ -91,46 +116,160 @@ class ConfigurationManager
|
||||
}
|
||||
}
|
||||
|
||||
public function isx64Platform() : bool {
|
||||
if (php_uname('m') === 'x86_64') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function isClamavEnabled() : bool {
|
||||
$config = $this->GetConfig();
|
||||
if (isset($config['isClamavEnabled']) && $config['isClamavEnabled'] === 1) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function SetClamavEnabledState(int $value) : void {
|
||||
$config = $this->GetConfig();
|
||||
$config['isClamavEnabled'] = $value;
|
||||
$this->WriteConfig($config);
|
||||
}
|
||||
|
||||
public function isOnlyofficeEnabled() : bool {
|
||||
$config = $this->GetConfig();
|
||||
if (isset($config['isOnlyofficeEnabled']) && $config['isOnlyofficeEnabled'] === 1) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function SetOnlyofficeEnabledState(int $value) : void {
|
||||
$config = $this->GetConfig();
|
||||
$config['isOnlyofficeEnabled'] = $value;
|
||||
$this->WriteConfig($config);
|
||||
}
|
||||
|
||||
public function isCollaboraEnabled() : bool {
|
||||
$config = $this->GetConfig();
|
||||
if (isset($config['isCollaboraEnabled']) && $config['isCollaboraEnabled'] === 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public function SetCollaboraEnabledState(int $value) : void {
|
||||
$config = $this->GetConfig();
|
||||
$config['isCollaboraEnabled'] = $value;
|
||||
$this->WriteConfig($config);
|
||||
}
|
||||
|
||||
public function isTalkEnabled() : bool {
|
||||
$config = $this->GetConfig();
|
||||
if (isset($config['isTalkEnabled']) && $config['isTalkEnabled'] === 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public function SetTalkEnabledState(int $value) : void {
|
||||
$config = $this->GetConfig();
|
||||
$config['isTalkEnabled'] = $value;
|
||||
$this->WriteConfig($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidSettingConfigurationException
|
||||
*/
|
||||
public function SetDomain(string $domain) : void {
|
||||
// Validate URL
|
||||
if (!filter_var('http://' . $domain, FILTER_VALIDATE_URL)) {
|
||||
throw new InvalidSettingConfigurationException("Domain is not in a valid format!");
|
||||
// Validate domain
|
||||
if (!filter_var($domain, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)) {
|
||||
throw new InvalidSettingConfigurationException("Domain is not a valid domain!");
|
||||
}
|
||||
|
||||
$dnsRecordIP = gethostbyname($domain);
|
||||
|
||||
// Validate IP
|
||||
if(!filter_var($dnsRecordIP, FILTER_VALIDATE_IP)) {
|
||||
throw new InvalidSettingConfigurationException("DNS config is not set or domain is not in a valid format!");
|
||||
// Validate that it is not an IP-address
|
||||
if(filter_var($domain, FILTER_VALIDATE_IP)) {
|
||||
throw new InvalidSettingConfigurationException("Please enter a domain and not an IP-address!");
|
||||
}
|
||||
|
||||
$connection = @fsockopen($domain, 443, $errno, $errstr, 0.1);
|
||||
if ($connection) {
|
||||
fclose($connection);
|
||||
} else {
|
||||
throw new InvalidSettingConfigurationException("The server is not reachable on Port 443.");
|
||||
}
|
||||
// Skip domain validation if opted in to do so
|
||||
if (!$this->shouldDomainValidationBeSkipped()) {
|
||||
|
||||
// Get Instance ID
|
||||
$instanceID = $this->GetSecret('INSTANCE_ID');
|
||||
$dnsRecordIP = gethostbyname($domain);
|
||||
if ($dnsRecordIP === $domain) {
|
||||
$dnsRecordIP = '';
|
||||
}
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL,'http://' . $domain . ':443');
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$response = curl_exec($ch);
|
||||
# Get rid of trailing \n
|
||||
$response = str_replace("\n", "", $response);
|
||||
if (empty($dnsRecordIP)) {
|
||||
$record = dns_get_record($domain, DNS_AAAA);
|
||||
if (!empty($record)) {
|
||||
$dnsRecordIP = $record[0]['ipv6'];
|
||||
}
|
||||
}
|
||||
|
||||
if($response !== $instanceID) {
|
||||
throw new InvalidSettingConfigurationException("Domain does not point to this server.");
|
||||
// Validate IP
|
||||
if (!filter_var($dnsRecordIP, FILTER_VALIDATE_IP)) {
|
||||
throw new InvalidSettingConfigurationException("DNS config is not set for this domain or the domain is not a valid domain! (It was found to be set to '" . $dnsRecordIP . "')");
|
||||
}
|
||||
|
||||
// Get the apache port
|
||||
$port = $this->GetApachePort();
|
||||
|
||||
if (!filter_var($dnsRecordIP, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
|
||||
$errorMessage = "It seems like the ip-address is set to an internal or reserved ip-address. This is not supported. (It was found to be set to '" . $dnsRecordIP . "')";
|
||||
if ($port === '443') {
|
||||
throw new InvalidSettingConfigurationException($errorMessage);
|
||||
} else {
|
||||
error_log($errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if port 443 is open
|
||||
$connection = @fsockopen($domain, 443, $errno, $errstr, 10);
|
||||
if ($connection) {
|
||||
fclose($connection);
|
||||
} else {
|
||||
throw new InvalidSettingConfigurationException("The server is not reachable on Port 443. You can verify this e.g. with 'https://portchecker.co/' by entering your domain there as ip-address and port 443 as port.");
|
||||
}
|
||||
|
||||
// Get Instance ID
|
||||
$instanceID = $this->GetSecret('INSTANCE_ID');
|
||||
|
||||
// set protocol
|
||||
if ($port !== '443') {
|
||||
$protocol = 'https://';
|
||||
} else {
|
||||
$protocol = 'http://';
|
||||
}
|
||||
|
||||
// Check if response is correct
|
||||
$ch = curl_init();
|
||||
$testUrl = $protocol . $domain . ':443';
|
||||
curl_setopt($ch, CURLOPT_URL, $testUrl);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$response = (string)curl_exec($ch);
|
||||
# Get rid of trailing \n
|
||||
$response = str_replace("\n", "", $response);
|
||||
|
||||
if ($response !== $instanceID) {
|
||||
error_log('The response of the connection attempt to "' . $testUrl . '" was: ' . $response);
|
||||
error_log('Expected was: ' . $instanceID);
|
||||
error_log('The error message was: ' . curl_error($ch));
|
||||
throw new InvalidSettingConfigurationException("Domain does not point to this server or the reverse proxy is not configured correctly. See the mastercontainer logs for more details. ('sudo docker logs -f nextcloud-aio-mastercontainer')");
|
||||
}
|
||||
}
|
||||
|
||||
// Write domain
|
||||
$config = $this->GetConfig();
|
||||
$config['domain'] = $domain;
|
||||
// Reset the borg restore password when setting the domain
|
||||
$config['borg_restore_password'] = '';
|
||||
$this->WriteConfig($config);
|
||||
}
|
||||
|
||||
@@ -152,6 +291,15 @@ class ConfigurationManager
|
||||
return $config['backup-mode'];
|
||||
}
|
||||
|
||||
public function GetSelectedRestoreTime() : string {
|
||||
$config = $this->GetConfig();
|
||||
if(!isset($config['selected-restore-time'])) {
|
||||
$config['selected-restore-time'] = '';
|
||||
}
|
||||
|
||||
return $config['selected-restore-time'];
|
||||
}
|
||||
|
||||
public function GetAIOURL() : string {
|
||||
$config = $this->GetConfig();
|
||||
if(!isset($config['AIO_URL'])) {
|
||||
@@ -165,25 +313,15 @@ class ConfigurationManager
|
||||
* @throws InvalidSettingConfigurationException
|
||||
*/
|
||||
public function SetBorgBackupHostLocation(string $location) : void {
|
||||
$allowedPrefixes = [
|
||||
'/mnt/',
|
||||
'/media/',
|
||||
];
|
||||
|
||||
$isValidPath = false;
|
||||
foreach($allowedPrefixes as $allowedPrefix) {
|
||||
if(str_starts_with($location, $allowedPrefix) && !str_ends_with($location, '/')) {
|
||||
$isValidPath = true;
|
||||
break;
|
||||
}
|
||||
if ($location === '/var/backups') {
|
||||
$isValidPath = true;
|
||||
break;
|
||||
}
|
||||
if (str_starts_with($location, '/') && !str_ends_with($location, '/')) {
|
||||
$isValidPath = true;
|
||||
} elseif ($location === 'nextcloud_aio_backupdir') {
|
||||
$isValidPath = true;
|
||||
}
|
||||
|
||||
if(!$isValidPath) {
|
||||
throw new InvalidSettingConfigurationException("The path must start with '/mnt/' or '/media/' or be equal to '/var/backups'.");
|
||||
if (!$isValidPath) {
|
||||
throw new InvalidSettingConfigurationException("The path must start with '/', and must not end with '/'!");
|
||||
}
|
||||
|
||||
|
||||
@@ -192,6 +330,78 @@ class ConfigurationManager
|
||||
$this->WriteConfig($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidSettingConfigurationException
|
||||
*/
|
||||
public function SetBorgRestoreHostLocationAndPassword(string $location, string $password) : void {
|
||||
if ($location === '') {
|
||||
throw new InvalidSettingConfigurationException("Please enter a path!");
|
||||
}
|
||||
|
||||
$isValidPath = false;
|
||||
if (str_starts_with($location, '/') && !str_ends_with($location, '/')) {
|
||||
$isValidPath = true;
|
||||
} elseif ($location === 'nextcloud_aio_backupdir') {
|
||||
$isValidPath = true;
|
||||
}
|
||||
|
||||
if (!$isValidPath) {
|
||||
throw new InvalidSettingConfigurationException("The path must start with '/', and must not end with '/'!");
|
||||
}
|
||||
|
||||
if ($password === '') {
|
||||
throw new InvalidSettingConfigurationException("Please enter the password!");
|
||||
}
|
||||
|
||||
$config = $this->GetConfig();
|
||||
$config['borg_backup_host_location'] = $location;
|
||||
$config['borg_restore_password'] = $password;
|
||||
$config['instance_restore_attempt'] = 1;
|
||||
$this->WriteConfig($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidSettingConfigurationException
|
||||
*/
|
||||
public function ChangeMasterPassword(string $currentPassword, string $newPassword) : void {
|
||||
if ($currentPassword === '') {
|
||||
throw new InvalidSettingConfigurationException("Please enter your current password.");
|
||||
}
|
||||
|
||||
if ($currentPassword !== $this->GetPassword()) {
|
||||
throw new InvalidSettingConfigurationException("The entered current password is not correct.");
|
||||
}
|
||||
|
||||
if ($newPassword === '') {
|
||||
throw new InvalidSettingConfigurationException("Please enter a new password.");
|
||||
}
|
||||
|
||||
if (strlen($newPassword) < 24) {
|
||||
throw new InvalidSettingConfigurationException("New passwords must be >= 24 digits.");
|
||||
}
|
||||
|
||||
if (!preg_match("#^[a-zA-Z0-9 ]+$#", $newPassword)) {
|
||||
throw new InvalidSettingConfigurationException('Not allowed characters in the new password.');
|
||||
}
|
||||
|
||||
// All checks pass so set the password
|
||||
$this->SetPassword($newPassword);
|
||||
}
|
||||
|
||||
public function GetApachePort() : string {
|
||||
$envVariableName = 'APACHE_PORT';
|
||||
$configName = 'apache_port';
|
||||
$defaultValue = '443';
|
||||
return $this->GetEnvironmentalVariableOrConfig($envVariableName, $configName, $defaultValue);
|
||||
}
|
||||
|
||||
public function GetTalkPort() : string {
|
||||
$envVariableName = 'TALK_PORT';
|
||||
$configName = 'talk_port';
|
||||
$defaultValue = '3478';
|
||||
return $this->GetEnvironmentalVariableOrConfig($envVariableName, $configName, $defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidSettingConfigurationException
|
||||
*/
|
||||
@@ -202,6 +412,28 @@ class ConfigurationManager
|
||||
file_put_contents(DataConst::GetConfigFile(), json_encode($config));
|
||||
}
|
||||
|
||||
private function GetEnvironmentalVariableOrConfig(string $envVariableName, string $configName, string $defaultValue) : string {
|
||||
$envVariableOutput = getenv($envVariableName);
|
||||
if ($envVariableOutput === false) {
|
||||
$config = $this->GetConfig();
|
||||
if (!isset($config[$configName]) || $config[$configName] === '') {
|
||||
$config[$configName] = $defaultValue;
|
||||
}
|
||||
return $config[$configName];
|
||||
}
|
||||
if(file_exists(DataConst::GetConfigFile())) {
|
||||
$config = $this->GetConfig();
|
||||
if (!isset($config[$configName])) {
|
||||
$config[$configName] = '';
|
||||
}
|
||||
if ($envVariableOutput !== $config[$configName]) {
|
||||
$config[$configName] = $envVariableOutput;
|
||||
$this->WriteConfig($config);
|
||||
}
|
||||
}
|
||||
return $envVariableOutput;
|
||||
}
|
||||
|
||||
public function GetBorgBackupHostLocation() : string {
|
||||
$config = $this->GetConfig();
|
||||
if(!isset($config['borg_backup_host_location'])) {
|
||||
@@ -211,6 +443,27 @@ class ConfigurationManager
|
||||
return $config['borg_backup_host_location'];
|
||||
}
|
||||
|
||||
public function GetBorgRestorePassword() : string {
|
||||
$config = $this->GetConfig();
|
||||
if(!isset($config['borg_restore_password'])) {
|
||||
$config['borg_restore_password'] = '';
|
||||
}
|
||||
|
||||
return $config['borg_restore_password'];
|
||||
}
|
||||
|
||||
public function isInstanceRestoreAttempt() : bool {
|
||||
$config = $this->GetConfig();
|
||||
if(!isset($config['instance_restore_attempt'])) {
|
||||
$config['instance_restore_attempt'] = '';
|
||||
}
|
||||
|
||||
if ($config['instance_restore_attempt'] === 1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function GetBorgBackupMode() : string {
|
||||
$config = $this->GetConfig();
|
||||
if(!isset($config['backup-mode'])) {
|
||||
@@ -219,4 +472,156 @@ class ConfigurationManager
|
||||
|
||||
return $config['backup-mode'];
|
||||
}
|
||||
|
||||
public function GetNextcloudMount() : string {
|
||||
$envVariableName = 'NEXTCLOUD_MOUNT';
|
||||
$configName = 'nextcloud_mount';
|
||||
$defaultValue = '';
|
||||
return $this->GetEnvironmentalVariableOrConfig($envVariableName, $configName, $defaultValue);
|
||||
}
|
||||
|
||||
public function GetNextcloudDatadirMount() : string {
|
||||
$envVariableName = 'NEXTCLOUD_DATADIR';
|
||||
$configName = 'nextcloud_datadir';
|
||||
$defaultValue = 'nextcloud_aio_nextcloud_data';
|
||||
return $this->GetEnvironmentalVariableOrConfig($envVariableName, $configName, $defaultValue);
|
||||
}
|
||||
|
||||
public function GetDockerSocketPath() : string {
|
||||
$envVariableName = 'DOCKER_SOCKET_PATH';
|
||||
$configName = 'docker_socket_path';
|
||||
$defaultValue = '/var/run/docker.sock';
|
||||
return $this->GetEnvironmentalVariableOrConfig($envVariableName, $configName, $defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidSettingConfigurationException
|
||||
*/
|
||||
public function SetDailyBackupTime(string $time, bool $enableAutomaticUpdates) : void {
|
||||
if ($time === "") {
|
||||
throw new InvalidSettingConfigurationException("The daily backup time must not be empty!");
|
||||
}
|
||||
|
||||
if (!preg_match("#^[0-1][0-9]:[0-5][0-9]$#", $time) && !preg_match("#^2[0-3]:[0-5][0-9]$#", $time)) {
|
||||
throw new InvalidSettingConfigurationException("You did not enter a correct time! One correct example is '04:00'!");
|
||||
}
|
||||
|
||||
if ($enableAutomaticUpdates === false) {
|
||||
$time .= PHP_EOL . 'automaticUpdatesAreNotEnabled';
|
||||
}
|
||||
file_put_contents(DataConst::GetDailyBackupTimeFile(), $time);
|
||||
}
|
||||
|
||||
public function GetDailyBackupTime() : string {
|
||||
if (!file_exists(DataConst::GetDailyBackupTimeFile())) {
|
||||
return '';
|
||||
}
|
||||
$dailyBackupFile = file_get_contents(DataConst::GetDailyBackupTimeFile());
|
||||
$dailyBackupFileArray = explode("\n", $dailyBackupFile);
|
||||
return $dailyBackupFileArray[0];
|
||||
}
|
||||
|
||||
public function areAutomaticUpdatesEnabled() : bool {
|
||||
if (!file_exists(DataConst::GetDailyBackupTimeFile())) {
|
||||
return false;
|
||||
}
|
||||
$dailyBackupFile = file_get_contents(DataConst::GetDailyBackupTimeFile());
|
||||
$dailyBackupFileArray = explode("\n", $dailyBackupFile);
|
||||
if (isset($dailyBackupFileArray[1]) && $dailyBackupFileArray[1] === 'automaticUpdatesAreNotEnabled') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public function DeleteDailyBackupTime() : void {
|
||||
if (file_exists(DataConst::GetDailyBackupTimeFile())) {
|
||||
unlink(DataConst::GetDailyBackupTimeFile());
|
||||
}
|
||||
}
|
||||
|
||||
public function isDailyBackupRunning() : bool {
|
||||
if (file_exists(DataConst::GetDailyBackupBlockFile())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function GetTimezone() : string {
|
||||
$config = $this->GetConfig();
|
||||
if(!isset($config['timezone'])) {
|
||||
$config['timezone'] = '';
|
||||
}
|
||||
|
||||
return $config['timezone'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidSettingConfigurationException
|
||||
*/
|
||||
public function SetTimezone(string $timezone) : void {
|
||||
if ($timezone === "") {
|
||||
throw new InvalidSettingConfigurationException("The timezone must not be empty!");
|
||||
}
|
||||
|
||||
if (!preg_match("#^[a-zA-Z0-9_\-\/\+]+$#", $timezone)) {
|
||||
throw new InvalidSettingConfigurationException("The entered timezone does not seem to be a valid timezone!");
|
||||
}
|
||||
|
||||
$config = $this->GetConfig();
|
||||
$config['timezone'] = $timezone;
|
||||
$this->WriteConfig($config);
|
||||
}
|
||||
|
||||
public function DeleteTimezone() : void {
|
||||
$config = $this->GetConfig();
|
||||
$config['timezone'] = '';
|
||||
$this->WriteConfig($config);
|
||||
}
|
||||
|
||||
public function shouldDomainValidationBeSkipped() : bool {
|
||||
if (getenv('SKIP_DOMAIN_VALIDATION') !== false) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function GetCollaboraDictionaries() : string {
|
||||
$config = $this->GetConfig();
|
||||
if(!isset($config['collabora_dictionaries'])) {
|
||||
$config['collabora_dictionaries'] = '';
|
||||
}
|
||||
|
||||
return $config['collabora_dictionaries'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidSettingConfigurationException
|
||||
*/
|
||||
public function SetCollaboraDictionaries(string $CollaboraDictionaries) : void {
|
||||
if ($CollaboraDictionaries === "") {
|
||||
throw new InvalidSettingConfigurationException("The dictionaries must not be empty!");
|
||||
}
|
||||
|
||||
if (!preg_match("#^[a-zA-Z_ ]+$#", $CollaboraDictionaries)) {
|
||||
throw new InvalidSettingConfigurationException("The entered dictionaries do not seem to be a valid!");
|
||||
}
|
||||
|
||||
$config = $this->GetConfig();
|
||||
$config['collabora_dictionaries'] = $CollaboraDictionaries;
|
||||
$this->WriteConfig($config);
|
||||
}
|
||||
|
||||
public function DeleteCollaboraDictionaries() : void {
|
||||
$config = $this->GetConfig();
|
||||
$config['collabora_dictionaries'] = '';
|
||||
$this->WriteConfig($config);
|
||||
}
|
||||
|
||||
public function GetApacheIPBinding() : string {
|
||||
$envVariableName = 'APACHE_IP_BINDING';
|
||||
$configName = 'apache_ip_binding';
|
||||
$defaultValue = '';
|
||||
return $this->GetEnvironmentalVariableOrConfig($envVariableName, $configName, $defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user