1
0
mirror of https://github.com/mailcow/mailcow-dockerized.git synced 2026-06-13 01:50:34 +00:00

Compare commits

..

72 Commits

Author SHA1 Message Date
Niklas Meyer 5470b51cc7 Merge pull request #4766 from mailcow/staging
2022-09
2022-09-27 15:53:31 +02:00
Niklas Meyer 8e0b1d8aee Merge pull request #4703 from devops-ansible/master
Improve send-as behaviour
2022-09-27 15:39:53 +02:00
Niklas Meyer 2834459b22 Merge pull request #4763 from ntimo/task/update-swagger
[API] Update swagger version
2022-09-27 11:16:44 +02:00
ntimo 000894dabd [API] Update swagger version 2022-09-26 19:33:31 +00:00
milkmaker 494620cdea [Web] Updated lang.tr.json (#4765)
Co-authored-by: Burak Buylu <burak@burtinet.com>
Co-authored-by: milkmaker <milkmaker@mailcow.de>

Co-authored-by: Burak Buylu <burak@burtinet.com>
2022-09-26 19:05:54 +02:00
Niklas Meyer a502eb239d Merge pull request #4758 from mailcow/feature/fix-4743 2022-09-26 18:41:40 +02:00
Niklas Meyer caf775093e Merge pull request #4762 from mindsolve/patch-1 2022-09-26 18:40:19 +02:00
Alex f28e18e676 GitHub Workflows security hardening (#4761)
* build: harden integration_tests.yml permissions

Signed-off-by: Alex <aleksandrosansan@gmail.com>

* build: harden image_builds.yml permissions

Signed-off-by: Alex <aleksandrosansan@gmail.com>

Signed-off-by: Alex <aleksandrosansan@gmail.com>
Co-authored-by: Niklas Meyer <62480600+DerLinkman@users.noreply.github.com>
2022-09-25 14:42:01 +02:00
Felix E b4bab1d5b9 Fixed typo in escape sequence in update script 2022-09-25 00:47:09 +02:00
Peter c4d5072e5c [GH-Actions][stale] Update to v6.0.0 2022-09-22 19:48:19 +02:00
Peter 852bf750ca Use utf8mb4 charset and utf8mb4_general_ci collation 2022-09-19 19:29:55 +02:00
Peter 47359c4113 [GH-Actions][stale] Update to v5.2.0 2022-09-16 22:00:22 +02:00
Niklas Meyer 15f2c4c769 Merge pull request #4749 from mailcow/staging
2022-08b
2022-09-08 13:02:49 +02:00
Niklas Meyer a0174c61e8 Merge pull request #4747 from mailcow/fix/sogo
Fix for SOGo in 2022-08
2022-09-08 12:34:26 +02:00
Niklas Meyer 5b30dce609 Merge pull request #4741 from maljes/master
Modified branch switch in generate_config.sh
2022-09-08 12:31:44 +02:00
FreddleSpl0it 8f6099e3e4 add &amp; to smtp url 2022-09-08 11:02:52 +02:00
FreddleSpl0it 7c44375223 increase dovecot and sogo image version 2022-09-08 10:35:03 +02:00
FreddleSpl0it 72e204f8fd fix sogo bugs after 2022-08 update 2022-09-08 10:32:07 +02:00
Malte Jesgarzewsky b5f5b53e37 Update generate_config.sh
Fixed bug in loop by replacing the variable.
2022-09-05 09:41:19 +02:00
Malte Jesgarzewsky 1c15133a52 Modified branch switch in generate_config.sh
Added possibility to define the mailcow branch by an environment variable to be able to bypass input.
2022-09-02 19:22:48 +02:00
Niklas Meyer 7c9c2c35f8 Merge pull request #4739 from mailcow/staging
2022-08a
2022-09-02 10:29:14 +02:00
DerLinkman 9806e568c0 Readded Sieve Location for Dovecot 2022-09-02 10:24:49 +02:00
DerLinkman b4bb4e2938 Improved compose version check (detect versions with v in front) 2022-09-02 10:05:11 +02:00
Niklas Meyer de7b809229 Merge pull request #4733 from mailcow/staging
Amoogus Update 2022 - Nightly Switch
2022-09-01 14:59:34 +02:00
FreddleSpl0it a40df1ff87 fix tfa modal trigger from dav/eas login 2022-09-01 09:53:08 +02:00
FreddleSpl0it a161aa2c92 remove testing debug log 2022-08-31 11:37:45 +02:00
FreddleSpl0it cad0f25345 Merge branch 'staging' of https://github.com/mailcow/mailcow-dockerized into staging 2022-08-31 11:31:59 +02:00
FreddleSpl0it 2ed453a400 fix mailbox tfa 2022-08-31 11:31:55 +02:00
DerLinkman 452d8a686f Merge branch 'master' into staging 2022-08-31 10:40:35 +02:00
Niklas Meyer 90f77f6d5c Merge pull request #4719 from mailcow/sogo-5.7.1
Update SOGo to 5.7.1
2022-08-29 11:57:18 +02:00
milkmaker 0c11cf747a Translations update from Weblate (#4722)
* [Web] Updated lang.cs.json [CI SKIP]

Co-authored-by: Vojtěch Kaizr <wojtishek@gmail.com>
Co-authored-by: milkmaker <milkmaker@mailcow.de>

* [Web] Updated lang.fr.json [CI SKIP]

Co-authored-by: milkmaker <milkmaker@mailcow.de>
Co-authored-by: ppelleti2 <pierre@ppelleti.fr>

* [Web] Updated lang.tr.json [CI SKIP]

[Web] Updated lang.tr.json [CI SKIP]

[Web] Updated lang.tr.json [CI SKIP]

[Web] Updated lang.tr.json [CI SKIP]

[Web] Updated lang.tr.json [CI SKIP]

[Web] Updated lang.tr.json [CI SKIP]

[Web] Updated lang.tr.json [CI SKIP]

[Web] Updated lang.tr.json [CI SKIP]

[Web] Updated lang.tr.json [CI SKIP]

[Web] Updated lang.tr.json [CI SKIP]

[Web] Updated lang.tr.json [CI SKIP]

[Web] Updated lang.tr.json [CI SKIP]

[Web] Updated lang.tr.json [CI SKIP]

[Web] Updated lang.tr.json [CI SKIP]

[Web] Updated lang.tr.json [CI SKIP]

[Web] Added lang.tr.json [CI SKIP]

Co-authored-by: Peter <magic@kthx.at>
Co-authored-by: milkmaker <milkmaker@mailcow.de>
Co-authored-by: therudeboy <abdullahozcelikisreklam@gmail.com>

* [Web] Updated lang.ro.json [CI SKIP]

Co-authored-by: Vlad M <vlad+mailcow@manoila.co.uk>
Co-authored-by: milkmaker <milkmaker@mailcow.de>

* [Web] Updated lang.it.json [CI SKIP]

Co-authored-by: Peter <magic@kthx.at>

* [Web] Turkish translation

* [Web] Turkish translation

Co-authored-by: Vojtěch Kaizr <wojtishek@gmail.com>
Co-authored-by: ppelleti2 <pierre@ppelleti.fr>
Co-authored-by: Peter <magic@kthx.at>
Co-authored-by: therudeboy <abdullahozcelikisreklam@gmail.com>
Co-authored-by: Vlad M <vlad+mailcow@manoila.co.uk>
2022-08-25 18:15:27 +02:00
Patrick Schult 6d36475ed3 Merge pull request #4725 from mailcow/feature/nightly-switch
[Update.sh] Nightly Version Switch implementation + Composev2 User Decision
2022-08-25 14:58:16 +02:00
DerLinkman fee6ff43bf Corrected compose standalone update message in generate config 2022-08-25 14:51:49 +02:00
DerLinkman 57cd5ec818 Readded update.sh new Version check :P 2022-08-25 14:48:38 +02:00
Patrick Schult 02512e0f4f Merge pull request #4685 from FreddleSpl0it/tfa-patch
Update TFA flow
2022-08-25 14:38:37 +02:00
FreddleSpl0it 555f4a8a6d [Web] Mailbox TFA fix 2022-08-25 14:26:45 +02:00
DerLinkman 3633766544 Fixed missing branch variable in app info.php (gen-config) 2022-08-25 11:21:12 +02:00
DerLinkman e98a984417 Implemented correct app_info.php set in generate_config 2022-08-25 11:16:55 +02:00
DerLinkman bc9141753f Re-arranged position of source mailcow.conf 2022-08-25 10:32:33 +02:00
DerLinkman 1f9f4157a6 Corrected detect docker compose command position 2022-08-25 10:27:46 +02:00
DerLinkman 778a3ed551 Use universal Git Commit Date Command 2022-08-25 10:07:42 +02:00
DerLinkman 5ea4305185 Fix Upstream Commit ID grep 2022-08-24 16:26:07 +02:00
DerLinkman ef311f22bf Corrected Twig Footer 2022-08-24 16:16:38 +02:00
DerLinkman e202530afb Set correct Commit ID from origin instead of local 2022-08-24 16:12:36 +02:00
DerLinkman 85deeaf806 Corrected origin fetch 2022-08-24 16:00:57 +02:00
DerLinkman 825c8a6abe Changed Git Checkout form 2022-08-24 15:56:02 +02:00
DerLinkman cdc8f63b4b Fixed Force flag 2022-08-24 15:05:14 +02:00
DerLinkman 9db9818ede Moved Force Mode check in prio 2022-08-24 15:00:39 +02:00
DerLinkman 4f7ee669d3 Added missing ;then in update.sh 2022-08-24 14:42:31 +02:00
DerLinkman 77f9947613 Readded footer + vars. 2022-08-24 14:37:00 +02:00
DerLinkman a8eb3b6ac5 Added nightly footer 2022-08-24 14:31:32 +02:00
DerLinkman 575eab1cf0 Implemented Check if IPv6 is disabled 2022-08-24 12:26:14 +02:00
DerLinkman 7a23e4fd4e Fix for Sieve error (due to IPv6 Comp from SOGo) 2022-08-24 12:12:41 +02:00
DerLinkman b16b276f36 Implement nightly/stable switch in update.sh 2022-08-23 14:04:40 +02:00
DerLinkman 4f380debb5 Added branch switch in generate_config.sh 2022-08-23 11:38:06 +02:00
DerLinkman 047c4aa3a0 Added seperate update_compose Script + some Improvements 2022-08-22 15:44:01 +02:00
DerLinkman 925b220905 Compose Version detection implemented in Backup script 2022-08-22 10:24:38 +02:00
DerLinkman 6708059227 Moved compose check to top.
Improved variable check.
2022-08-19 15:55:24 +02:00
DerLinkman 1f3d9d4e1c Implemented user choice compose in cold-standby 2022-08-19 15:17:19 +02:00
Peter 0dcfac8f15 Update SOGo to 5.7.1 2022-08-18 19:06:54 +02:00
andryyy ad8b7f0894 [Dovecot] Fixes broken sieve compiler in some rare cases when using replication 2022-08-18 15:08:00 +02:00
DerLinkman 55f810b23f Implemented new compose check in update.sh 2022-08-17 16:00:58 +02:00
DerLinkman 65eddee63e New variable for mailcow.conf in generate_config.sh 2022-08-17 14:39:12 +02:00
Niklas Meyer 4322c98f73 [UI] Moved PWChange Button for users back to original place 2022-08-05 14:12:25 +02:00
macwinnie edcf789126 Update postfix version by +.1
Update Version of Docker-Image according to [related comment](https://github.com/mailcow/mailcow-dockerized/pull/4703#issuecomment-1205277142)
2022-08-05 00:37:58 +02:00
macwinnie b985ba4f0e Improve send-as behaviour
Receiving mails for wildcard alias addresses is really easy – but
sending mails from those any-aliases was not possible at all unless
every sender address was added as an explicit alias to the database.

By this change in the database query for allowed sender addresses, the
first finding `not NULL` (see [`SELECT COALESCE`](https://www.w3schools.com/sql/func_sqlserver_coalesce.asp) for how it works)
– either an exact alias `mailbox@domain.tld` or the wildcard alias `@domain.tld`
will be allowed to send mails as the given address ... without the need
of explicit definition within the database.
2022-08-04 01:37:26 +02:00
Peter 67c0405274 [GH-Actions][stale] Update to v5.1.1 2022-08-02 19:06:04 +02:00
Peter 9b32151ab5 [GH-Actions][stale] Update to v5.1.1 2022-08-02 19:04:05 +02:00
FreddleSpl0it c8620a066d yubi_otp undo authenticator selection 2022-07-15 16:45:28 +02:00
FreddleSpl0it 1ca566f670 autoselect authenticator if only one exists 2022-07-15 13:02:13 +02:00
FreddleSpl0it 0342ae926c exclude oauth clients & app passwords from mailbox tfa 2022-07-14 18:55:35 +02:00
FreddleSpl0it be08742653 exclude oauth clients & app passwords from mailbox tfa 2022-07-14 18:37:21 +02:00
43 changed files with 709 additions and 316 deletions
@@ -14,7 +14,7 @@ jobs:
pull-requests: write
steps:
- name: Mark/Close Stale Issues and Pull Requests 🗑️
uses: actions/stale@v5.1.0
uses: actions/stale@v6.0.0
with:
repo-token: ${{ secrets.STALE_ACTION_PAT }}
days-before-stale: 60
+3
View File
@@ -5,6 +5,9 @@ on:
branches: [ "master", "staging" ]
workflow_dispatch:
permissions:
contents: read # to fetch code (actions/checkout)
jobs:
docker_image_builds:
strategy:
+3
View File
@@ -5,6 +5,9 @@ on:
branches: [ "master", "staging" ]
workflow_dispatch:
permissions:
contents: read
jobs:
integration_tests:
runs-on: ubuntu-latest
@@ -307,6 +307,7 @@ namespace {
}
EOF
cat <<EOF > /etc/dovecot/sogo_trusted_ip.conf
# Autogenerated by mailcow
remote ${IPV4_NETWORK}.248 {
@@ -349,6 +350,14 @@ sievec /var/vmail/sieve/global_sieve_after.sieve
sievec /usr/lib/dovecot/sieve/report-spam.sieve
sievec /usr/lib/dovecot/sieve/report-ham.sieve
for file in /var/vmail/*/*/sieve/*.sieve ; do
if [[ "$file" == "/var/vmail/*/*/sieve/*.sieve" ]]; then
continue
fi
sievec "$file" "$(dirname "$file")/../.dovecot.svbin"
chown vmail:vmail "$(dirname "$file")/../.dovecot.svbin"
done
# Fix permissions
chown root:root /etc/dovecot/sql/*.conf
chown root:dovecot /etc/dovecot/sql/dovecot-dict-sql-sieve* /etc/dovecot/sql/dovecot-dict-sql-quota* /etc/dovecot/lua/passwd-verify.lua
@@ -50,7 +50,7 @@ try:
def query_mysql(query, headers = True, update = False):
while True:
try:
cnx = mysql.connector.connect(unix_socket = '/var/run/mysqld/mysqld.sock', user=os.environ.get('DBUSER'), passwd=os.environ.get('DBPASS'), database=os.environ.get('DBNAME'), charset="utf8")
cnx = mysql.connector.connect(unix_socket = '/var/run/mysqld/mysqld.sock', user=os.environ.get('DBUSER'), passwd=os.environ.get('DBPASS'), database=os.environ.get('DBNAME'), charset="utf8mb4", collation="utf8mb4_general_ci")
except Exception as ex:
print('%s - trying again...' % (ex))
time.sleep(3)
@@ -166,4 +166,4 @@ try:
notify_rcpt(record['rcpt'], record['counter'], record['quarantine_acl'], attrs['quarantine_category'])
finally:
os.unlink(pidfile)
os.unlink(pidfile)
+14 -2
View File
@@ -323,7 +323,19 @@ hosts = unix:/var/run/mysqld/mysqld.sock
dbname = ${DBNAME}
# First select queries domain and alias_domain to determine if domains are active.
query = SELECT goto FROM alias
WHERE address='%s'
WHERE id IN (
SELECT COALESCE (
(
SELECT id FROM alias
WHERE address='%s'
AND (active='1' OR active='2')
), (
SELECT id FROM alias
WHERE address='@%d'
AND (active='1' OR active='2')
)
)
)
AND active='1'
AND (domain IN
(SELECT domain FROM domain
@@ -354,7 +366,7 @@ query = SELECT goto FROM alias
WHERE alias_domain.alias_domain = '%d'
AND mailbox.username = CONCAT('%u','@',alias_domain.target_domain)
AND (mailbox.active = '1' OR mailbox.active ='2')
AND alias_domain.active='1'
AND alias_domain.active='1';
EOF
# MX based routing
+3 -3
View File
@@ -2,7 +2,7 @@ FROM debian:bullseye-slim
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
ARG DEBIAN_FRONTEND=noninteractive
ARG SOGO_DEBIAN_REPOSITORY=http://packages.inverse.ca/SOGo/nightly/5/debian/
ARG SOGO_DEBIAN_REPOSITORY=http://packages.sogo.nu/nightly/5/debian/
ENV LC_ALL C
ENV GOSU_VERSION 1.14
@@ -30,7 +30,7 @@ RUN echo "Building from repository $SOGO_DEBIAN_REPOSITORY" \
&& gosu nobody true \
&& mkdir /usr/share/doc/sogo \
&& touch /usr/share/doc/sogo/empty.sh \
&& apt-key adv --keyserver keyserver.ubuntu.com --recv-key 0x810273C4 \
&& apt-key adv --keyserver keys.openpgp.org --recv-key 74FFC6D72B925A34B5D356BDF8A27B36A6E2EAE9 \
&& echo "deb ${SOGO_DEBIAN_REPOSITORY} bullseye bullseye" > /etc/apt/sources.list.d/sogo.list \
&& apt-get update && apt-get install -y --no-install-recommends \
sogo \
@@ -52,4 +52,4 @@ RUN chmod +x /bootstrap-sogo.sh \
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
CMD exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
+4
View File
@@ -142,6 +142,10 @@ cat <<EOF > /var/lib/sogo/GNUstep/Defaults/sogod.plist
<string>mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/sogo_acl</string>
<key>SOGoIMAPServer</key>
<string>imap://${IPV4_NETWORK}.250:143/?TLS=YES&amp;tlsVerifyMode=none</string>
<key>SOGoSieveServer</key>
<string>sieve://${IPV4_NETWORK}.250:4190/?TLS=YES&amp;tlsVerifyMode=none</string>
<key>SOGoSMTPServer</key>
<string>smtp://${IPV4_NETWORK}.253:588/?TLS=YES&amp;tlsVerifyMode=none</string>
<key>SOGoTrustProxyAuthentication</key>
<string>YES</string>
<key>SOGoEncryptionKey</key>
-2
View File
@@ -32,8 +32,6 @@
// );
// self-signed is not trusted anymore
SOGoSieveServer = "sieve://dovecot:4190/?TLS=YES&tlsVerifyMode=none";
SOGoSMTPServer = "smtp://postfix:588/?TLS=YES&tlsVerifyMode=none";
WOPort = "0.0.0.0:20000";
SOGoMemcachedHost = "memcached";
+16
View File
@@ -0,0 +1,16 @@
html {
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 0;
background: #fafafa;
}
+2 -43
View File
@@ -5,56 +5,15 @@
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
<link rel="stylesheet" type="text/css" href="index.css" />
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
<style>
html
{
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after
{
box-sizing: inherit;
}
body
{
margin:0;
background: #fafafa;
}
</style>
</head>
<body>
<div id="swagger-ui"></div>
<script src="./swagger-ui-bundle.js" charset="UTF-8"> </script>
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
<script>
window.onload = function() {
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
urls: [{url: "/api/openapi.yaml", name: "mailcow API"}],
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
});
// End Swagger UI call region
window.ui = ui;
};
</script>
<script src="./swagger-initializer.js" charset="UTF-8"> </script>
</body>
</html>
+10 -6
View File
@@ -13,7 +13,7 @@
var isValid, qp, arr;
if (/code|token|error/.test(window.location.hash)) {
qp = window.location.hash.substring(1);
qp = window.location.hash.substring(1).replace('?', '&');
} else {
qp = location.search.substring(1);
}
@@ -38,7 +38,7 @@
authId: oauth2.auth.name,
source: "auth",
level: "warning",
message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"
message: "Authorization may be unsafe, passed state was changed in server. The passed state wasn't returned from auth server."
});
}
@@ -58,7 +58,7 @@
authId: oauth2.auth.name,
source: "auth",
level: "error",
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server"
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server."
});
}
} else {
@@ -67,9 +67,13 @@
window.close();
}
window.addEventListener('DOMContentLoaded', function () {
run();
});
if (document.readyState !== 'loading') {
run();
} else {
document.addEventListener('DOMContentLoaded', function () {
run();
});
}
</script>
</body>
</html>
+19
View File
@@ -0,0 +1,19 @@
window.onload = function() {
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
urls: [{url: "/api/openapi.yaml", name: "mailcow API"}],
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
});
// End Swagger UI call region
window.ui = ui;
};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
View File
@@ -269,6 +269,7 @@ code {
padding: 10px;
background: #fbfbfb;
border: 1px solid #ededed;
min-height: 110px;
}
.tag-box {
+8 -1
View File
@@ -48,7 +48,14 @@ if (isset($pending_tfa_authmechs['u2f'])) {
$globalVariables = [
'mailcow_info' => array(
'version_tag' => $GLOBALS['MAILCOW_GIT_VERSION'],
'git_project_url' => $GLOBALS['MAILCOW_GIT_URL']
'last_version_tag' => $GLOBALS['MAILCOW_LAST_GIT_VERSION'],
'git_owner' => $GLOBALS['MAILCOW_GIT_OWNER'],
'git_repo' => $GLOBALS['MAILCOW_GIT_REPO'],
'git_project_url' => $GLOBALS['MAILCOW_GIT_URL'],
'git_commit' => $GLOBALS['MAILCOW_GIT_COMMIT'],
'git_commit_date' => $GLOBALS['MAILCOW_GIT_COMMIT_DATE'],
'mailcow_branch' => $GLOBALS['MAILCOW_BRANCH'],
'updated_at' => $GLOBALS['MAILCOW_UPDATEDAT']
),
'js_path' => '/cache/'.basename($JSPath),
'pending_tfa_methods' => @$_SESSION['pending_tfa_methods'],
+38 -34
View File
@@ -935,38 +935,47 @@ function check_login($user, $pass, $app_passwd_data = false) {
$stmt->execute(array(':user' => $user));
$rows = array_merge($rows, $stmt->fetchAll(PDO::FETCH_ASSOC));
}
foreach ($rows as $row) {
foreach ($rows as $row) {
// verify password
if (verify_hash($row['password'], $pass) !== false) {
// check for tfa authenticators
$authenticators = get_tfa($user);
if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0) {
$_SESSION['pending_mailcow_cc_username'] = $user;
$_SESSION['pending_mailcow_cc_role'] = "user";
$_SESSION['pending_tfa_methods'] = $authenticators['additional'];
unset($_SESSION['ldelay']);
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $user, '*'),
'msg' => array('logged_in_as', $user)
);
return "pending";
} else {
if ($app_passwd_data['eas'] === true || $app_passwd_data['dav'] === true) {
$service = ($app_passwd_data['eas'] === true) ? 'EAS' : 'DAV';
$stmt = $pdo->prepare("REPLACE INTO sasl_log (`service`, `app_password`, `username`, `real_rip`) VALUES (:service, :app_id, :username, :remote_addr)");
$stmt->execute(array(
':service' => $service,
':app_id' => $row['app_passwd_id'],
':username' => $user,
':remote_addr' => ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'])
));
if (!array_key_exists("app_passwd_id", $row)){
// password is not a app password
// check for tfa authenticators
$authenticators = get_tfa($user);
if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0 &&
$app_passwd_data['eas'] !== true && $app_passwd_data['dav'] !== true) {
// authenticators found, init TFA flow
$_SESSION['pending_mailcow_cc_username'] = $user;
$_SESSION['pending_mailcow_cc_role'] = "user";
$_SESSION['pending_tfa_methods'] = $authenticators['additional'];
unset($_SESSION['ldelay']);
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $user, '*'),
'msg' => array('logged_in_as', $user)
);
return "pending";
} else if (!isset($authenticators['additional']) || !is_array($authenticators['additional']) || count($authenticators['additional']) == 0) {
// no authenticators found, login successfull
// Reactivate TFA if it was set to "deactivate TFA for next login"
$stmt = $pdo->prepare("UPDATE `tfa` SET `active`='1' WHERE `username` = :user");
$stmt->execute(array(':user' => $user));
unset($_SESSION['ldelay']);
return "user";
}
} elseif ($app_passwd_data['eas'] === true || $app_passwd_data['dav'] === true) {
// password is a app password
$service = ($app_passwd_data['eas'] === true) ? 'EAS' : 'DAV';
$stmt = $pdo->prepare("REPLACE INTO sasl_log (`service`, `app_password`, `username`, `real_rip`) VALUES (:service, :app_id, :username, :remote_addr)");
$stmt->execute(array(
':service' => $service,
':app_id' => $row['app_passwd_id'],
':username' => $user,
':remote_addr' => ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'])
));
unset($_SESSION['ldelay']);
// Reactivate TFA if it was set to "deactivate TFA for next login"
$stmt = $pdo->prepare("UPDATE `tfa` SET `active`='1' WHERE `username` = :user");
$stmt->execute(array(':user' => $user));
return "user";
}
}
@@ -1626,12 +1635,8 @@ function verify_tfa_login($username, $_data) {
global $WebAuthn;
if ($_data['tfa_method'] != 'u2f'){
$stmt = $pdo->prepare("SELECT `authmech` FROM `tfa`
WHERE `username` = :username AND `id` = :id AND `active` = '1'");
$stmt->execute(array(':username' => $username, ':id' => $_data['id']));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
switch ($row["authmech"]) {
switch ($_data["tfa_method"]) {
case "yubi_otp":
if (!ctype_alnum($_data['token']) || strlen($_data['token']) != 44) {
$_SESSION['return'][] = array(
@@ -1645,10 +1650,9 @@ function verify_tfa_login($username, $_data) {
$stmt = $pdo->prepare("SELECT `id`, `secret` FROM `tfa`
WHERE `username` = :username
AND `authmech` = 'yubi_otp'
AND `id` = :id
AND `active` = '1'
AND `secret` LIKE :modhex");
$stmt->execute(array(':username' => $username, ':modhex' => '%' . $yubico_modhex_id, ':id' => $_data['id']));
$stmt->execute(array(':username' => $username, ':modhex' => '%' . $yubico_modhex_id));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$yubico_auth = explode(':', $row['secret']);
$yubi = new Auth_Yubico($yubico_auth[0], $yubico_auth[1]);
+1
View File
@@ -100,6 +100,7 @@ $AVAILABLE_LANGUAGES = array(
'ru' => 'Pусский (Russian)',
'sk' => 'Slovenčina (Slovak)',
'sv' => 'Svenska (Swedish)',
'tr' => 'Türkçe (Turkish)',
'uk' => 'Українська (Ukrainian)',
'zh' => '中文 (Chinese)'
);
+1 -1
View File
@@ -839,7 +839,7 @@
"confirm_delete": "Potvrdit smazání prvku.",
"danger": "Nebezpečí",
"deliver_inbox": "Doručit do schránky",
"disabled_by_config": "Funkce karanténa je momentálně vypnuta v nastavení systému.",
"disabled_by_config": "Funkce karanténa je momentálně vypnuta v nastavení systému. Nastavte, prosím, prvkům karantény hodnoty \"počet zadržených zpráv\" a \"maximální velikost\".",
"download_eml": "Stáhnout (.eml)",
"empty": "Žádné výsledky",
"high_danger": "Vysoké nebezpečí",
+5 -2
View File
@@ -102,7 +102,8 @@
"timeout2": "Délai d'expiration pour la connexion à l'hôte local",
"username": "Nom d'utilisateur",
"validate": "Valider",
"validation_success": "Validation réussie"
"validation_success": "Validation réussie",
"bcc_dest_format": "La destination Cci doit être une seule adresse e-mail valide.<br>Si vous avez besoin d'envoyer une copie à plusieurs adresses, créez un alias et utilisez-le ici."
},
"admin": {
"access": "Accès",
@@ -322,7 +323,9 @@
"yes": "&#10003;",
"api_read_write": "Accès Lecture-Écriture",
"oauth2_add_client": "Ajouter un client OAuth2",
"password_policy": "Politique de mots de passe"
"password_policy": "Politique de mots de passe",
"admins": "Administrateurs",
"api_read_only": "Accès lecture-seule"
},
"danger": {
"access_denied": "Accès refusé ou données de formulaire non valides",
+2 -1
View File
@@ -973,7 +973,8 @@
"verified_fido2_login": "Verified FIDO2 login",
"verified_totp_login": "Verified TOTP login",
"verified_webauthn_login": "Verified WebAuthn login",
"verified_yotp_login": "Verified Yubico OTP login"
"verified_yotp_login": "Verified Yubico OTP login",
"domain_add_dkim_available": "Esisteva già una chiave DKIM"
},
"tfa": {
"api_register": "%s usa le API Yubico Cloud. Richiedi una chiave API <a href=\"https://upgrade.yubico.com/getapikey/\" target=\"_blank\">qui</a>",
+3 -2
View File
@@ -979,7 +979,8 @@
"verified_totp_login": "Autentificarea TOTP verificată",
"verified_webauthn_login": "Autentificarea WebAuthn verificată",
"verified_fido2_login": "Conectare FIDO2 verificată",
"verified_yotp_login": "Autentificarea Yubico OTP verificată"
"verified_yotp_login": "Autentificarea Yubico OTP verificată",
"domain_add_dkim_available": "O cheie DKIM deja a existat"
},
"tfa": {
"api_register": "%s utilizează API-ul Yubico Cloud. Obțineți o cheie API pentru cheia dvs. de <a href=\"https://upgrade.yubico.com/getapikey/\" target=\"_blank\">aici</a>",
@@ -990,7 +991,7 @@
"enter_qr_code": "Codul tău TOTP dacă dispozitivul tău nu poate scana codurile QR",
"error_code": "Cod de eroare",
"init_webauthn": "Inițializare, vă rugăm așteptați...",
"key_id": "Un identificator pentru YubiKey",
"key_id": "Un identificator pentru dispozitiv",
"key_id_totp": "Un identificator pentru cheia ta",
"none": "Dezactivează",
"reload_retry": "- (reîncărcați browserul dacă eroarea persistă)",
+86
View File
@@ -0,0 +1,86 @@
{
"acl": {
"alias_domains": "Takma alan adı ekle",
"app_passwds": "Uygulama şifrelerini yönet",
"delimiter_action": "Sınırlama işlemi",
"domain_relayhost": "Bir alan adı için relayhost sunucusunu değiştir",
"eas_reset": "EAS cihazlarını sıfırla",
"mailbox_relayhost": "Bir posta kutusunun relayhost sunucularını değiştir",
"pushover": "Bildirim",
"quarantine": "Karantina işlemleri",
"quarantine_attachments": "Ekleri karantinaya al",
"quarantine_notification": "Karantina bildirimlerini değiştir",
"smtp_ip_access": "SMTP sunucularının değiştirilmesine izin ver",
"sogo_access": "SOGo erişiminin yönetilmesine izin ver",
"domain_desc": "Alan adı açıklamasını değiştir",
"extend_sender_acl": "Gönderenin acl'sini harici adreslere göre genişletmeye izin ver",
"spam_policy": "Engellenenler / İzin verilenler",
"filters": "Fitreler"
},
"add": {
"activate_filter_warn": "Aktif edilirse diğer tüm filtreler devre dışı bırakılacak.",
"add_domain_only": "Sadece alan adı ekle",
"alias_address": "Takma ad adres(leri)",
"alias_domain": "Takma alan adı",
"alias_domain_info": "<small>Sadece geçerli alan adları (virgülle ayırın).</small>",
"backup_mx_options": "İletme ayarları",
"delete2": "Kaynakta olmayan hedefteki mesajları sil",
"delete2duplicates": "Hedefteki kopyaları sil",
"disable_login": "Giriş yapmaya izin verme ( Gelen mailler yine de kabul edilir)",
"domain": "Alan adı",
"domain_matches_hostname": "Alan adı %s ana bilgisayar adıyla eşleşiyor",
"add_domain_restart": "Alan adı ekleyin ve SOGo'yu yeniden başlatın",
"alias_address_info": "<small>Bir alan adına ilişkin tüm iletileri yakalamak için tam e-posta adresi veya @example.com olacak şeklinde girin (virgülle ayırın).<b>sadece mailcow alan adları</b>.</small>",
"domain_quota_m": "Toplam alan adı kotası (MiB)",
"generate": "oluştur",
"goto_ham": "Ham olarak<span class=\"text-success\"><b>işaretle</b></span>",
"goto_null": "Postaları sessizce çöpe at",
"goto_spam": "Spam olarak<span class=\"text-danger\"><b>işaretle</b></span>",
"hostname": "Ana sunucu",
"kind": "Tür",
"mailbox_quota_m": "Posta kutusu başına maksimum kota (MiB)",
"max_aliases": "Maksimum olası takma adı",
"max_mailboxes": "Maksimum olası posta kutusu",
"nexthop": "Sonraki atlama",
"port": "Port",
"public_comment": "Genel yorum",
"relay_all": "Tüm alıcılara ilet",
"relay_all_info": "Eğer <b>hiçbir</b> alıcıya iletilmemesini seçerseniz, aktarılması gereken her alıcı için bir (\"kör\") posta kutusu eklemeniz gerekecektir.",
"relay_domain": "Bu alan adını ilet",
"relay_transport_info": "<div class=\"label label-info\">Bilgi</div> Bu etki alanı için özel bir hedef için aktarım eşlemeleri tanımlayabilirsiniz. Ayarlanmazsa, bir MX araması yapılacaktır.",
"relay_unknown_only": "Yalnızca mevcut olmayan posta kutularını ilet. Mevcut posta kutuları yerel olarak teslim edilecektir.",
"relayhost_wrapped_tls_info": "Lütfen TLS ile örtülmüş portları <b> kullanmayın</b> (çoğu 465 portunda çalışır).<br>\nÖrtülmemiş port kullan ve STARTTLS üzerinden yayınla. TLS'yi zorlamak için bir TLS ilkesi \"TLS ilke eşlemeleri\" sayfası içinde oluşturulabilir.",
"skipcrossduplicates": "Klasörler arasında yinelenen mesajları atlayın (ilk mesaj seçilir)",
"target_address": "Adreslere git",
"target_address_info": "<small>Tam e-posta adres(leri) girin ( virgülle ayırın).</small>",
"target_domain": "Hedef alan adı",
"timeout1": "Uzak ana bilgisayara bağlantısı zaman aşımına uğradı",
"timeout2": "Yerel ana bilgisayara bağlantı zaman aşımına uğradı"
},
"admin": {
"action": "İşlem",
"add_forwarding_host": "Yönlendirme sunucusu ekle",
"add_transport": "İletim ekle",
"admin_details": "Yönetici detaylarını düzenle",
"admin_domains": "Alan adı atamaları",
"add_domain_admin": "Alan adı yöneticisi ekle",
"api_info": "API üzerinde çalışmalar devam etmektedir. Belgeler <a href=\"/api\">/api</a>adresinde bulunabilir",
"apps_name": "\"mailcow Uygulamaları\" adı",
"authed_user": "Yetkili kullanıcı",
"ban_list_info": "Aşağıdaki yasaklı IP'lerin listesine bakın: <b>ağ (kalan yasak süresi) - [işlemler]</b>.<br />Yasağı kaldırılmak üzere sıraya alınan IP'ler birkaç saniye içinde aktif yasak listesinden kaldırılacaktır.<br />Kırmızı etiketler, kara listeye alınarak aktif kalıcı yasakları gösterir.",
"configuration": "Yapılandırma",
"dkim_from_title": "Verilerin kopyalanacağı kaynak alan adı",
"dkim_to": "Kime",
"dkim_to_title": "Hedef alan ad(ları) üzerinde yazılacak",
"dkim_domains_wo_keys": "Eksik anahtarları olan alan adlarını seçin",
"domain": "Alan adı",
"domain_admin": "Alan adı yöneticisi",
"domain_admins": "Alan adı yöneticileri",
"domain_s": "Alan ad(ları)",
"duplicate": "Çift",
"duplicate_dkim": "Çift DKIM kayıtları",
"f2b_ban_time": "Yasaklama süresi (saniye)",
"f2b_max_attempts": "Maksimum giriş denemesi",
"f2b_retry_window": "Maksimum girişim için deneme pencere(leri)"
}
}
+44 -24
View File
@@ -182,30 +182,19 @@ function recursiveBase64StrToArrayBuffer(obj) {
keyboard: false
});
// validate Yubi OTP tfa
$("#pending_tfa_tab_yubi_otp").click(function(){
$(".totp-authenticator-selection").removeClass("active");
$(".webauthn-authenticator-selection").removeClass("active");
$("#collapseTotpTFA").collapse('hide');
$("#collapseWebAuthnTFA").collapse('hide');
});
$(".yubi-authenticator-selection").click(function(){
$(".yubi-authenticator-selection").removeClass("active");
$(this).addClass("active");
var id = $(this).children('input').first().val();
$("#yubi_selected_id").val(id);
$("#collapseYubiTFA").collapse('show');
});
// validate Time based OTP tfa
$("#pending_tfa_tab_totp").click(function(){
$(".yubi-authenticator-selection").removeClass("active");
$(".webauthn-authenticator-selection").removeClass("active");
$("#collapseYubiTFA").collapse('hide');
$("#collapseWebAuthnTFA").collapse('hide');
// select default if only one authenticator exists
if ($('.totp-authenticator-selection').length == 1){
$('.totp-authenticator-selection').addClass("active");
var id = $('.totp-authenticator-selection').children('input').first().val();
$("#totp_selected_id").val(id);
$("#collapseTotpTFA").collapse('show');
}
});
$(".totp-authenticator-selection").click(function(){
$(".totp-authenticator-selection").removeClass("active");
@@ -216,13 +205,37 @@ function recursiveBase64StrToArrayBuffer(obj) {
$("#collapseTotpTFA").collapse('show');
});
if ($('.totp-authenticator-selection').length == 1 &&
$('#pending_tfa_tab_yubi_otp').length == 0 &&
$('.webauthn-authenticator-selection').length == 0){
// select default if only one authenticator exists
$('.totp-authenticator-selection').addClass("active");
var id = $('.totp-authenticator-selection').children('input').first().val();
$("#totp_selected_id").val(id);
$("#collapseTotpTFA").collapse('show');
setTimeout(function() { $("#collapseTotpTFA").find('input[name="token"]').focus(); }, 1000);
}
$('#pending_tfa_tab_totp').on('shown.bs.tab', function() {
// autofocus
setTimeout(function() { $("#collapseTotpTFA").find('input[name="token"]').focus(); }, 200);
});
// validate Yubi OTP tfa
if ($('.webauthn-authenticator-selection').length == 0){
// autofocus
setTimeout(function() { $("#collapseYubiTFA").find('input[name="token"]').focus(); }, 1000);
}
$('#pending_tfa_tab_yubi_otp').on('shown.bs.tab', function() {
// autofocus
$("#collapseYubiTFA").find('input[name="token"]').focus();
});
// validate WebAuthn tfa
$("#pending_tfa_tab_webauthn").click(function(){
$(".totp-authenticator-selection").removeClass("active");
$(".yubi-authenticator-selection").removeClass("active");
$("#collapseTotpTFA").collapse('hide');
$("#collapseYubiTFA").collapse('hide');
});
$(".webauthn-authenticator-selection").click(function(){
$(".webauthn-authenticator-selection").removeClass("active");
@@ -477,13 +490,20 @@ function recursiveBase64StrToArrayBuffer(obj) {
{% if ui_texts.ui_footer %}
<hr><span class="rot-enc">{{ ui_texts.ui_footer|rot13|raw }}</span>
{% endif %}
{% if mailcow_cc_username and mailcow_info.version_tag|default %}
{% if mailcow_cc_username and mailcow_info.mailcow_branch|lower == "master" and mailcow_info.version_tag|default %}
<span class="version">
🐮 + 🐋 = 💕
<a href="{{ mailcow_info.git_project_url }}/releases/tag/{{ mailcow_info.version_tag }}" target="_blank">
Version: {{ mailcow_info.version_tag }}
Version: <a href="{{ mailcow_info.git_project_url }}/releases/tag/{{ mailcow_info.version_tag }}" target="_blank">{{ mailcow_info.version_tag }}
</a>
</span>
{% endif %}
{% if mailcow_cc_username and mailcow_info.mailcow_branch|lower == "nightly" and mailcow_info.version_tag|default %}
<span class="version">
🛠️🐮 + 🐋 = 💕
Nightly: <a href="{{ mailcow_info.git_project_url }}/commit/{{ mailcow_info.git_commit }}" target="_blank">{{ mailcow_info.version_tag }}
</a><br>
<span style="text-align:right;display:block;">Build: {{ mailcow_info.git_commit_date }}</span>
</span>
{% endif %}
</div>
</body>
+2 -13
View File
@@ -206,20 +206,9 @@
<form role="form" method="post">
<legend>
<i class="bi bi-shield-fill-check"></i>
Authenticators
Authenticate
</legend>
<div class="list-group">
{% for authenticator in pending_tfa_methods %}
{% if authenticator["authmech"] == "yubi_otp" %}
<a href="#" class="list-group-item yubi-authenticator-selection">
<i class="bi bi-key-fill" style="margin-right: 5px"></i>
<span>{{ authenticator["key_id"] }}</span>
<input type="hidden" value="{{ authenticator["id"] }}" />
</a>
{% endif %}
{% endfor %}
</div>
<div class="collapse pending-tfa-collapse" id="collapseYubiTFA">
<div class="collapse in pending-tfa-collapse" id="collapseYubiTFA">
<div class="form-group">
<div class="input-group">
<span class="input-group-addon" id="yubi-addon"><img alt="Yubicon Icon" src="/img/yubi.ico"></span>
+2 -4
View File
@@ -18,10 +18,6 @@
<i class="bi bi-inbox-fill"></i> {{ lang.user.open_webmail_sso }}
</a>
{% endif %}
<div>
<hr>
<p><a href="#pwChangeModal" data-toggle="modal"><i class="bi bi-pencil-fill"></i> {{ lang.user.change_password }}</a></p>
</div>
</div>
</div>
<hr>
@@ -47,6 +43,8 @@
</div>
</div>
<p>{{ mailboxdata.quota_used|formatBytes(2) }} / {% if mailboxdata.quota == 0 %}{% else %}{{ mailboxdata.quota|formatBytes(2) }}{% endif %}<br>{{ mailboxdata.messages }} {{ lang.user.messages }}</p>
<hr>
<p><a href="#pwChangeModal" data-toggle="modal"><i class="bi bi-pencil-fill"></i> {{ lang.user.change_password }}</a></p>
</div>
</div>
<hr>
+3 -3
View File
@@ -168,7 +168,7 @@ services:
- phpfpm
sogo-mailcow:
image: mailcow/sogo:1.109
image: mailcow/sogo:1.111
environment:
- DBNAME=${DBNAME}
- DBUSER=${DBUSER}
@@ -215,7 +215,7 @@ services:
- sogo
dovecot-mailcow:
image: mailcow/dovecot:1.17
image: mailcow/dovecot:1.20
depends_on:
- mysql-mailcow
dns:
@@ -295,7 +295,7 @@ services:
- dovecot
postfix-mailcow:
image: mailcow/postfix:1.67
image: mailcow/postfix:1.68
depends_on:
- mysql-mailcow
volumes:
+102 -12
View File
@@ -16,19 +16,49 @@ if [[ "$(uname -r)" =~ ^4\.4\. ]]; then
fi
fi
if grep --help 2>&1 | grep -q -i "busybox"; then
echo "BusyBox grep detected, please install gnu grep, \"apk add --no-cache --upgrade grep\""
exit 1
fi
if cp --help 2>&1 | grep -q -i "busybox"; then
echo "BusyBox cp detected, please install coreutils, \"apk add --no-cache --upgrade coreutils\""
exit 1
fi
if grep --help 2>&1 | head -n 1 | grep -q -i "busybox"; then echo "BusyBox grep detected, please install gnu grep, \"apk add --no-cache --upgrade grep\""; exit 1; fi
# This will also cover sort
if cp --help 2>&1 | head -n 1 | grep -q -i "busybox"; then echo "BusyBox cp detected, please install coreutils, \"apk add --no-cache --upgrade coreutils\""; exit 1; fi
if sed --help 2>&1 | head -n 1 | grep -q -i "busybox"; then echo "BusyBox sed detected, please install gnu sed, \"apk add --no-cache --upgrade sed\""; exit 1; fi
for bin in openssl curl docker docker-compose git awk sha1sum; do
for bin in openssl curl docker git awk sha1sum; do
if [[ -z $(which ${bin}) ]]; then echo "Cannot find ${bin}, exiting..."; exit 1; fi
done
if docker compose > /dev/null 2>&1; then
if docker compose version --short | grep "^2." > /dev/null 2>&1; then
COMPOSE_VERSION=native
echo -e "\e[31mFound Docker Compose Plugin (native).\e[0m"
echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable to native\e[0m"
sleep 2
echo -e "\e[33mNotice: You´ll have to update this Compose Version via your Package Manager manually!\e[0m"
else
echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m"
echo -e "\e[31mPlease update/install it manually regarding to this doc site: https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m"
exit 1
fi
elif docker-compose > /dev/null 2>&1; then
if ! [[ $(alias docker-compose 2> /dev/null) ]] ; then
if docker-compose version --short | grep "^2." > /dev/null 2>&1; then
COMPOSE_VERSION=standalone
echo -e "\e[31mFound Docker Compose Standalone.\e[0m"
echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable to standalone\e[0m"
sleep 2
echo -e "\e[33mNotice: For an automatic update of docker-compose please use the update_compose.sh scripts located at the helper-scripts folder.\e[0m"
else
echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m"
echo -e "\e[31mPlease update/install manually regarding to this doc site: https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m"
exit 1
fi
fi
else
echo -e "\e[31mCannot find Docker Compose.\e[0m"
echo -e "\e[31mPlease install it regarding to this doc site: https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m"
exit 1
fi
if [ -f mailcow.conf ]; then
read -r -p "A config file exists and will be overwritten, are you sure you want to continue? [y/N] " response
case $response in
@@ -105,6 +135,32 @@ else
SKIP_SOLR=n
fi
echo "Which branch of mailcow do you want to use?"
echo ""
echo "Available Branches:"
echo "- master branch (stable updates) | default, recommended [1]"
echo "- nightly branch (unstable updates, testing) | not-production ready [2]"
sleep 1
while [ -z "${MAILCOW_BRANCH}" ]; do
read -r -p "Choose the Branch with it´s number [1/2] " branch
case $branch in
[2])
MAILCOW_BRANCH="nightly"
;;
*)
MAILCOW_BRANCH="master"
;;
esac
done
if [ ! -z "${MAILCOW_BRANCH}" ]; then
git_branch=${MAILCOW_BRANCH}
fi
git fetch --all
git checkout -f $git_branch
[ ! -f ./data/conf/rspamd/override.d/worker-controller-password.inc ] && echo '# Placeholder' > ./data/conf/rspamd/override.d/worker-controller-password.inc
cat << EOF > mailcow.conf
@@ -183,6 +239,14 @@ TZ=${MAILCOW_TZ}
COMPOSE_PROJECT_NAME=mailcowdockerized
# Used Docker Compose version
# Switch here between native (compose plugin) and standalone
# For more informations take a look at the mailcow docs regarding the configuration options.
# Normally this should be untouched but if you decided to use either of those you can switch it manually here.
# Please be aware that at least one of those variants should be installed on your maschine or mailcow will fail.
DOCKER_COMPOSE_VERSION=${COMPOSE_VERSION}
# Set this to "allow" to enable the anyone pseudo user. Disabled by default.
# When enabled, ACL can be created, that apply to "All authenticated users"
# This should probably only be activated on mail hosts, that are used exclusivly by one organisation.
@@ -363,16 +427,42 @@ echo "Copying snake-oil certificate..."
cp -n -d data/assets/ssl-example/*.pem data/assets/ssl/
# Set app_info.inc.php
mailcow_git_version=$(git describe --tags `git rev-list --tags --max-count=1`)
if [ ${git_branch} == "master" ]; then
mailcow_git_version=$(git describe --tags `git rev-list --tags --max-count=1`)
elif [ ${git_branch} == "nightly" ]; then
mailcow_git_version=$(git rev-parse --short $(git rev-parse @{upstream}))
mailcow_last_git_version=""
else
mailcow_git_version=$(git rev-parse --short HEAD)
mailcow_last_git_version=""
fi
mailcow_git_commit=$(git rev-parse origin/${git_branch})
mailcow_git_commit_date=$(git log -1 --format=%ci @{upstream} )
if [ $? -eq 0 ]; then
echo '<?php' > data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_VERSION="'$mailcow_git_version'";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_LAST_GIT_VERSION="";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_OWNER="mailcow";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_REPO="mailcow-dockerized";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_URL="https://github.com/mailcow/mailcow-dockerized";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_COMMIT="'$mailcow_git_commit'";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_COMMIT_DATE="'$mailcow_git_commit_date'";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_BRANCH="'$git_branch'";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_UPDATEDAT='$(date +%s)';' >> data/web/inc/app_info.inc.php
echo '?>' >> data/web/inc/app_info.inc.php
else
echo '<?php' > data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_VERSION="";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_URL="";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_VERSION="'$mailcow_git_version'";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_LAST_GIT_VERSION="";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_OWNER="mailcow";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_REPO="mailcow-dockerized";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_URL="https://github.com/mailcow/mailcow-dockerized";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_COMMIT="";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_COMMIT_DATE="";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_BRANCH="'$git_branch'";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_UPDATEDAT='$(date +%s)';' >> data/web/inc/app_info.inc.php
echo '?>' >> data/web/inc/app_info.inc.php
echo -e "\e[33mCannot determine current git repository version...\e[0m"
fi
+37 -19
View File
@@ -77,7 +77,7 @@ function preflight_local_checks() {
exit 1
fi
for bin in rsync docker docker-compose grep cut; do
for bin in rsync docker grep cut; do
if [[ -z $(which ${bin}) ]]; then
>&2 echo -e "\e[31mCannot find ${bin} in local PATH, exiting...\e[0m"
exit 1
@@ -111,7 +111,7 @@ function preflight_remote_checks() {
exit 1
fi
for bin in rsync docker docker-compose; do
for bin in rsync docker; do
if ! ssh -o StrictHostKeyChecking=no \
-i "${REMOTE_SSH_KEY}" \
${REMOTE_SSH_HOST} \
@@ -121,17 +121,44 @@ function preflight_remote_checks() {
exit 1
fi
done
ssh -o StrictHostKeyChecking=no \
-i "${REMOTE_SSH_KEY}" \
${REMOTE_SSH_HOST} \
-p ${REMOTE_SSH_PORT} \
"bash -s" << "EOF"
if docker compose > /dev/null 2>&1; then
exit 0
elif docker-compose version --short | grep "^2." > /dev/null 2>&1; then
exit 1
else
exit 2
fi
EOF
if [ $? = 0 ]; then
COMPOSE_COMMAND="docker compose"
echo "DEBUG: Using native docker compose on remote"
elif [ $? = 1 ]; then
COMPOSE_COMMAND="docker-compose"
echo "DEBUG: Using standalone docker compose on remote"
else
echo -e "\e[31mCannot find any Docker Compose on remote, exiting...\e[0m"
exit 1
fi
}
SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
source "${SCRIPT_DIR}/../mailcow.conf"
COMPOSE_FILE="${SCRIPT_DIR}/../docker-compose.yml"
CMPS_PRJ=$(echo ${COMPOSE_PROJECT_NAME} | tr -cd 'A-Za-z-_')
SQLIMAGE=$(grep -iEo '(mysql|mariadb)\:.+' "${COMPOSE_FILE}")
preflight_local_checks
preflight_remote_checks
SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
COMPOSE_FILE="${SCRIPT_DIR}/../docker-compose.yml"
source "${SCRIPT_DIR}/../mailcow.conf"
CMPS_PRJ=$(echo ${COMPOSE_PROJECT_NAME} | tr -cd 'A-Za-z-_')
SQLIMAGE=$(grep -iEo '(mysql|mariadb)\:.+' "${COMPOSE_FILE}")
echo
echo -e "\033[1mFound compose project name ${CMPS_PRJ} for ${MAILCOW_HOSTNAME}\033[0m"
echo -e "\033[1mFound SQL ${SQLIMAGE}\033[0m"
@@ -258,7 +285,7 @@ echo "OK"
-i "${REMOTE_SSH_KEY}" \
${REMOTE_SSH_HOST} \
-p ${REMOTE_SSH_PORT} \
docker-compose -f "${SCRIPT_DIR}/../docker-compose.yml" pull --no-parallel --quiet 2>&1 ; then
${COMPOSE_COMMAND} -f "${SCRIPT_DIR}/../docker-compose.yml" pull --no-parallel --quiet 2>&1 ; then
>&2 echo -e "\e[31m[ERR]\e[0m - Could not pull images on remote"
fi
@@ -271,13 +298,4 @@ if ! ssh -o StrictHostKeyChecking=no \
>&2 echo -e "\e[31m[ERR]\e[0m - Could not cleanup old images on remote"
fi
echo -e "\033[1mExecuting update script and checking for new docker-compose Version on remote...\033[0m"
if ! ssh -o StrictHostKeyChecking=no \
-i "${REMOTE_SSH_KEY}" \
${REMOTE_SSH_HOST} \
-p ${REMOTE_SSH_PORT} \
${SCRIPT_DIR}/../update.sh -f --update-compose ; then
>&2 echo -e "\e[31m[ERR]\e[0m - Could not fetch docker-compose on remote"
fi
echo -e "\e[32mDone\e[0m"
echo -e "\e[32mDone\e[0m"
+16 -4
View File
@@ -160,12 +160,24 @@ function backup() {
}
function restore() {
for bin in docker docker-compose; do
for bin in docker; do
if [[ -z $(which ${bin}) ]]; then
>&2 echo -e "\e[31mCannot find ${bin} in local PATH, exiting...\e[0m"
exit 1
fi
done
done
if [ "${DOCKER_COMPOSE_VERSION}" == "native" ]; then
COMPOSE_COMMAND="docker compose"
elif [ "${DOCKER_COMPOSE_VERSION}" == "standalone" ]; then
COMPOSE_COMMAND="docker-compose"
else
echo -e "\e[31mCan not read DOCKER_COMPOSE_VERSION variable from mailcow.conf! Is your mailcow up to date? Exiting...\e[0m"
exit 1
fi
echo
echo "Stopping watchdog-mailcow..."
docker stop $(docker ps -qf name=watchdog-mailcow)
@@ -244,7 +256,7 @@ function restore() {
continue
else
echo "Stopping mailcow..."
docker-compose -f ${COMPOSE_FILE} --env-file ${ENV_FILE} down
${COMPOSE_COMMAND} -f ${COMPOSE_FILE} --env-file ${ENV_FILE} down
fi
#docker stop $(docker ps -qf name=mysql-mailcow)
if [[ -d "${RESTORE_LOCATION}/mysql" ]]; then
@@ -282,7 +294,7 @@ function restore() {
sed -i --follow-symlinks "/DBROOT/c\DBROOT=${DBROOT}" ${SCRIPT_DIR}/../mailcow.conf
source ${SCRIPT_DIR}/../mailcow.conf
echo "Starting mailcow..."
docker-compose -f ${COMPOSE_FILE} --env-file ${ENV_FILE} up -d
${COMPOSE_COMMAND} -f ${COMPOSE_FILE} --env-file ${ENV_FILE} up -d
#docker start $(docker ps -aqf name=mysql-mailcow)
fi
;;
+70
View File
@@ -0,0 +1,70 @@
#!/bin/bash
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source ${SCRIPT_DIR}/../mailcow.conf
if [ "${DOCKER_COMPOSE_VERSION}" == "standalone" ]; then
LATEST_COMPOSE=$(curl -#L https://www.servercow.de/docker-compose/latest.php)
COMPOSE_VERSION=$(docker-compose version --short)
if [[ "$LATEST_COMPOSE" != "$COMPOSE_VERSION" ]]; then
echo -e "\e[33mA new docker-compose Version is available: $LATEST_COMPOSE\e[0m"
echo -e "\e[33mYour Version is: $COMPOSE_VERSION\e[0m"
else
echo -e "\e[32mYour docker-compose Version is up to date! Not updating it...\e[0m"
exit 0
fi
read -r -p "Do you want to update your docker-compose Version? It will automatic upgrade your docker-compose installation (recommended)? [y/N] " updatecomposeresponse
if [[ ! "${updatecomposeresponse}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
echo "OK, not updating docker-compose."
exit 0
fi
echo -e "\e[32mFetching new docker-compose (standalone) version...\e[0m"
echo -e "\e[32mTrying to determine GLIBC version...\e[0m"
if ldd --version > /dev/null; then
GLIBC_V=$(ldd --version | grep -E '(GLIBC|GNU libc)' | rev | cut -d ' ' -f1 | rev | cut -d '.' -f2)
if [ ! -z "${GLIBC_V}" ] && [ ${GLIBC_V} -gt 27 ]; then
DC_DL_SUFFIX=
else
DC_DL_SUFFIX=legacy
fi
else
DC_DL_SUFFIX=legacy
fi
sleep 1
if [[ $(command -v pip 2>&1) && $(pip list --local 2>&1 | grep -v DEPRECATION | grep -c docker-compose) == 1 || $(command -v pip3 2>&1) && $(pip3 list --local 2>&1 | grep -v DEPRECATION | grep -c docker-compose) == 1 ]]; then
echo -e "\e[33mFound a docker-compose Version installed with pip!\e[0m"
echo -e "\e[31mPlease uninstall the pip Version of docker-compose since it doesn´t support Versions higher than 1.29.2.\e[0m"
sleep 2
echo -e "\e[33mExiting...\e[0m"
exit 1
#prevent breaking a working docker-compose installed with pip
elif [[ $(curl -sL -w "%{http_code}" https://www.servercow.de/docker-compose/latest.php?vers=${DC_DL_SUFFIX} -o /dev/null) == "200" ]]; then
LATEST_COMPOSE=$(curl -#L https://www.servercow.de/docker-compose/latest.php)
COMPOSE_VERSION=$(docker-compose version --short)
if [[ "$LATEST_COMPOSE" != "$COMPOSE_VERSION" ]]; then
COMPOSE_PATH=$(command -v docker-compose)
if [[ -w ${COMPOSE_PATH} ]]; then
curl -#L https://github.com/docker/compose/releases/download/v${LATEST_COMPOSE}/docker-compose-$(uname -s)-$(uname -m) > $COMPOSE_PATH
chmod +x $COMPOSE_PATH
echo -e "\e[32mYour Docker Compose (standalone) has been updated to: $LATEST_COMPOSE\e[0m"
exit 0
else
echo -e "\e[33mWARNING: $COMPOSE_PATH is not writable, but new version $LATEST_COMPOSE is available (installed: $COMPOSE_VERSION)\e[0m"
return 1
fi
fi
else
echo -e "\e[33mCannot determine latest docker-compose version, skipping...\e[0m"
exit 1
fi
elif [ "${DOCKER_COMPOSE_VERSION}" == "native" ]; then
echo -e "\e[31mYou are using the native Docker Compose Plugin. This Script is for the standalone Docker Compose Version only.\e[0m"
sleep 2
echo -e "\e[33mNotice: You´ll have to update this Compose Version via your Package Manager manually!\e[0m"
exit 1
else
echo -e "\e[31mCan not read DOCKER_COMPOSE_VERSION variable from mailcow.conf! Is your mailcow up to date? Exiting...\e[0m"
exit 1
fi
+190 -123
View File
@@ -175,58 +175,48 @@ remove_obsolete_nginx_ports() {
done
}
update_compose(){
if [[ ${NO_UPDATE_COMPOSE} == "y" ]]; then
echo -e "\e[33mNot fetching latest docker-compose, please check for updates manually!\e[0m"
return 0
elif [[ -e /etc/alpine-release ]]; then
echo -e "\e[33mNot fetching latest docker-compose, because you are using Alpine Linux without glibc support. Please update docker-compose via apk!\e[0m"
return 0
else
if [ ! $FORCE ]; then
read -r -p "Do you want to update your docker-compose Version? It will automatic upgrade your docker-compose installation (recommended)? [y/N] " updatecomposeresponse
if [[ ! "${updatecomposeresponse}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
echo "OK, not updating docker-compose."
return 0
fi
fi
echo -e "\e[32mFetching new docker-compose version...\e[0m"
echo -e "\e[32mTrying to determine GLIBC version...\e[0m"
if ldd --version > /dev/null; then
GLIBC_V=$(ldd --version | grep -E '(GLIBC|GNU libc)' | rev | cut -d ' ' -f1 | rev | cut -d '.' -f2)
if [ ! -z "${GLIBC_V}" ] && [ ${GLIBC_V} -gt 27 ]; then
DC_DL_SUFFIX=
else
DC_DL_SUFFIX=legacy
fi
else
DC_DL_SUFFIX=legacy
fi
sleep 1
if [[ $(command -v pip 2>&1) && $(pip list --local 2>&1 | grep -v DEPRECATION | grep -c docker-compose) == 1 || $(command -v pip3 2>&1) && $(pip3 list --local 2>&1 | grep -v DEPRECATION | grep -c docker-compose) == 1 ]]; then
echo -e "\e[33mFound a docker-compose Version installed with pip!\e[0m"
echo -e "\e[31mPlease uninstall the pip Version of docker-compose since it doesn´t support Versions higher than 1.29.2.\e[0m"
sleep 2
echo -e "\e[33mExiting...\e[0m"
exit 1
#prevent breaking a working docker-compose installed with pip
elif [[ $(curl -sL -w "%{http_code}" https://www.servercow.de/docker-compose/latest.php?vers=${DC_DL_SUFFIX} -o /dev/null) == "200" ]]; then
LATEST_COMPOSE=$(curl -#L https://www.servercow.de/docker-compose/latest.php)
COMPOSE_VERSION=$(docker-compose version --short)
if [[ "$LATEST_COMPOSE" != "$COMPOSE_VERSION" ]]; then
COMPOSE_PATH=$(command -v docker-compose)
if [[ -w ${COMPOSE_PATH} ]]; then
curl -#L https://github.com/docker/compose/releases/download/v${LATEST_COMPOSE}/docker-compose-$(uname -s)-$(uname -m) > $COMPOSE_PATH
chmod +x $COMPOSE_PATH
detect_docker_compose_command(){
if ! [ "${DOCKER_COMPOSE_VERSION}" == "native" ] && ! [ "${DOCKER_COMPOSE_VERSION}" == "standalone" ]; then
if docker compose > /dev/null 2>&1; then
if docker compose version --short | grep "2." > /dev/null 2>&1; then
DOCKER_COMPOSE_VERSION=native
COMPOSE_COMMAND="docker compose"
echo -e "\e[31mFound Docker Compose Plugin (native).\e[0m"
echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable to native\e[0m"
sleep 2
echo -e "\e[33mNotice: You'll have to update this Compose Version via your Package Manager manually!\e[0m"
else
echo -e "\e[33mWARNING: $COMPOSE_PATH is not writable, but new version $LATEST_COMPOSE is available (installed: $COMPOSE_VERSION)\e[0m"
return 1
echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m"
echo -e "\e[31mPlease update/install it manually regarding to this doc site: https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m"
exit 1
fi
elif docker-compose > /dev/null 2>&1; then
if ! [[ $(alias docker-compose 2> /dev/null) ]] ; then
if docker-compose version --short | grep "^2." > /dev/null 2>&1; then
DOCKER_COMPOSE_VERSION=standalone
COMPOSE_COMMAND="docker-compose"
echo -e "\e[31mFound Docker Compose Standalone.\e[0m"
echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable to standalone\e[0m"
sleep 2
echo -e "\e[33mNotice: For an automatic update of docker-compose please use the update_compose.sh scripts located at the helper-scripts folder.\e[0m"
else
echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m"
echo -e "\e[31mPlease update/install regarding to this doc site: https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m"
exit 1
fi
fi
else
echo -e "\e[33mCannot determine latest docker-compose version, skipping...\e[0m"
return 1
echo -e "\e[31mCannot find Docker Compose.\e[0m"
echo -e "\e[31mPlease install it regarding to this doc site: https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m"
exit 1
fi
elif [ "${DOCKER_COMPOSE_VERSION}" == "native" ]; then
COMPOSE_COMMAND="docker compose"
elif [ "${DOCKER_COMPOSE_VERSION}" == "standalone" ]; then
COMPOSE_COMMAND="docker-compose"
fi
}
@@ -272,6 +262,10 @@ PATH=$PATH:/opt/bin
umask 0022
# Unset COMPOSE_COMMAND and DOCKER_COMPOSE_VERSION Variable to be on the newest state.
unset COMPOSE_COMMAND
unset DOCKER_COMPOSE_VERSION
for bin in curl docker git awk sha1sum; do
if [[ -z $(command -v ${bin}) ]]; then
echo "Cannot find ${bin}, exiting..."
@@ -279,13 +273,6 @@ for bin in curl docker git awk sha1sum; do
fi
done
if [[ -z $(command -v docker-compose) ]]; then
echo -e "\e[31mCannot find docker-compose Standalone.\e[0m"
echo -e "\e[31mPlease install it manually regarding to this doc site: https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m"
sleep 3
exit 1;
fi
export LC_ALL=C
DATE=$(date +%Y-%m-%d_%H_%M_%S)
BRANCH=$(cd ${SCRIPT_DIR}; git rev-parse --abbrev-ref HEAD)
@@ -314,11 +301,22 @@ while (($#)); do
--skip-start)
SKIP_START=y
;;
--skip-ping-check)
SKIP_PING_CHECK=y
;;
--stable)
CURRENT_BRANCH="$(cd ${SCRIPT_DIR}; git rev-parse --abbrev-ref HEAD)"
NEW_BRANCH="master"
;;
--gc)
echo -e "\e[32mCollecting garbage...\e[0m"
docker_garbage
exit 0
;;
--nightly)
CURRENT_BRANCH="$(cd ${SCRIPT_DIR}; git rev-parse --abbrev-ref HEAD)"
NEW_BRANCH="nightly"
;;
--prefetch)
echo -e "\e[32mPrefetching images...\e[0m"
prefetch_images
@@ -328,36 +326,17 @@ while (($#)); do
echo -e "\e[32mRunning in forced mode...\e[0m"
FORCE=y
;;
--no-update-compose)
NO_UPDATE_COMPOSE=y
;;
--update-compose)
LATEST_COMPOSE=$(curl -#L https://www.servercow.de/docker-compose/latest.php)
COMPOSE_VERSION=$(docker-compose version --short)
if [[ "$LATEST_COMPOSE" != "$COMPOSE_VERSION" ]]; then
echo -e "\e[33mA new docker-compose Version is available: $LATEST_COMPOSE\e[0m"
echo -e "\e[33mYour Version is: $COMPOSE_VERSION\e[0m"
update_compose
echo -e "\e[32mYour docker-compose Version is now up to date!\e[0m"
else
echo -e "\e[32mYour docker-compose Version is up to date! Not updating it...\e[0m"
fi
exit 0
;;
--skip-ping-check)
SKIP_PING_CHECK=y
;;
--help|-h)
echo './update.sh [-c|--check, --ours, --gc, --no-update-compose, --update-compose, --prefetch, --skip-start, --skip-ping-check, -f|--force, -h|--help]
echo './update.sh [-c|--check, --ours, --gc, --nightly, --prefetch, --skip-start, --skip-ping-check, --stable, -f|--force, -h|--help]
-c|--check - Check for updates and exit (exit codes => 0: update available, 3: no updates)
--ours - Use merge strategy option "ours" to solve conflicts in favor of non-mailcow code (local changes over remote changes), not recommended!
--gc - Run garbage collector to delete old image tags
--no-update-compose - Skip the docker-compose Updates during the mailcow Update process
--update-compose - Only run the docker-compose Update process (don´t updates your mailcow itself)
--nightly - Switch your mailcow updates to the unstable (nightly) branch. FOR TESTING PURPOSES ONLY!!!!
--prefetch - Only prefetch new images and exit (useful to prepare updates)
--skip-start - Do not start mailcow after update
--skip-ping-check - Skip ICMP Check to public DNS resolvers (Use it only if you´ve blocked any ICMP Connections to your mailcow machine)
--stable - Switch your mailcow updates to the stable (master) branch. Default unless you changed it with --nightly.
-f|--force - Force update, do not ask questions
'
exit 1
@@ -365,28 +344,16 @@ while (($#)); do
shift
done
# Check if Docker-Compose is older then v2 before continuing
if ! docker-compose version --short | grep "^2." > /dev/null 2>&1; then
echo -e "\e[33mYour docker-compose Version is not up to date!\e[0m"
echo -e "\e[33mmailcow needs docker-compose > 2.X.X!\e[0m"
echo -e "\e[33mYour current installed Version: $(docker-compose version --short)\e[0m"
sleep 3
update_compose
if [[ ! "${updatecomposeresponse}" =~ ^([yY][eE][sS]|[yY])+$ ]] && [[ ! ${FORCE} ]]; then
echo -e "\e[31mmailcow does not work with docker-compose < 2.X.X anymore!\e[0m"
echo -e "\e[31mPlease update your docker-compose manually, to run mailcow.\e[0m"
echo -e "\e[31mExiting...\e[0m"
exit 1
fi
fi
[[ ! -f mailcow.conf ]] && { echo "mailcow.conf is missing"; exit 1;}
chmod 600 mailcow.conf
source mailcow.conf
detect_docker_compose_command
[[ ! -f mailcow.conf ]] && { echo "mailcow.conf is missing! Is mailcow installed?"; exit 1;}
DOTS=${MAILCOW_HOSTNAME//[^.]};
if [ ${#DOTS} -lt 2 ]; then
echo "MAILCOW_HOSTNAME (${MAILCOW_HOSTNAME}) is not a FQDN!"
echo "Please change it to a FQDN and run docker-compose down followed by docker-compose up -d"
echo "Please change it to a FQDN and run $COMPOSE_COMMAND down followed by $COMPOSE_COMMAND up -d"
exit 1
fi
@@ -413,6 +380,7 @@ CONFIG_ARRAY=(
"SNAT_TO_SOURCE"
"SNAT6_TO_SOURCE"
"COMPOSE_PROJECT_NAME"
"DOCKER_COMPOSE_VERSION"
"SQL_PORT"
"API_KEY"
"API_KEY_READ_ONLY"
@@ -448,6 +416,17 @@ for option in ${CONFIG_ARRAY[@]}; do
echo "Adding new option \"${option}\" to mailcow.conf"
echo "COMPOSE_PROJECT_NAME=mailcowdockerized" >> mailcow.conf
fi
elif [[ ${option} == "DOCKER_COMPOSE_VERSION" ]]; then
if ! grep -q ${option} mailcow.conf; then
echo "Adding new option \"${option}\" to mailcow.conf"
echo "# Used Docker Compose version" >> mailcow.conf
echo "# Switch here between native (compose plugin) and standalone" >> mailcow.conf
echo "# For more informations take a look at the mailcow docs regarding the configuration options." >> mailcow.conf
echo "# Normally this should be untouched but if you decided to use either of those you can switch it manually here." >> mailcow.conf
echo "# Please be aware that at least one of those variants should be installed on your maschine or mailcow will fail." >> mailcow.conf
echo "" >> mailcow.conf
echo "DOCKER_COMPOSE_VERSION=${DOCKER_COMPOSE_VERSION}" >> mailcow.conf
fi
elif [[ ${option} == "DOVEADM_PORT" ]]; then
if ! grep -q ${option} mailcow.conf; then
echo "Adding new option \"${option}\" to mailcow.conf"
@@ -672,6 +651,82 @@ else
fi
fi
if ! [ $NEW_BRANCH ]; then
echo -e "\e[33mDetecting which build your mailcow runs on...\e[0m"
sleep 1
if [ ${BRANCH} == "master" ]; then
echo -e "\e[32mYou are receiving stable updates (master).\e[0m"
echo -e "\e[33mTo change that run the update.sh Script one time with the --nightly parameter to switch to nightly builds.\e[0m"
elif [ ${BRANCH} == "nightly" ]; then
echo -e "\e[31mYou are receiving unstable updates (nightly). These are for testing purposes only!!!\e[0m"
sleep 1
echo -e "\e[33mTo change that run the update.sh Script one time with the --stable parameter to switch to stable builds.\e[0m"
else
echo -e "\e[33mYou are receiving updates from a unsupported branch.\e[0m"
sleep 1
echo -e "\e[33mThe mailcow stack might still work but it is recommended to switch to the master branch (stable builds).\e[0m"
echo -e "\e[33mTo change that run the update.sh Script one time with the --stable parameter to switch to stable builds.\e[0m"
fi
elif [ $FORCE ]; then
echo -e "\e[31mYou are running in forced mode!\e[0m"
echo -e "\e[31mA Branch Switch can only be performed manually (monitored).\e[0m"
echo -e "\e[31mPlease rerun the update.sh Script without the --force/-f parameter.\e[0m"
sleep 1
elif [ $NEW_BRANCH == "master" ] && [ $CURRENT_BRANCH != "master" ]; then
echo -e "\e[33mYou are about to switch your mailcow Updates to the stable (master) branch.\e[0m"
sleep 1
echo -e "\e[33mBefore you do: Please take a backup of all components to ensure that no Data is lost...\e[0m"
sleep 1
echo -e "\e[31mWARNING: Please see on GitHub or ask in the communitys if a switch to master is stable or not.
In some rear cases a Update back to master can destroy your mailcow configuration in case of Database Upgrades etc.
Normally a upgrade back to master should be safe during each full release.
Check GitHub for Database Changes and Update only if there similar to the full release!\e[0m"
read -r -p "Are you sure you that want to continue upgrading to the stable (master) branch? [y/N] " response
if [[ ! "${response}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
echo "OK. If you prepared yourself for that please run the update.sh Script with the --stable parameter again to trigger this process here."
exit 0
fi
BRANCH=$NEW_BRANCH
DIFF_DIRECTORY=update_diffs
DIFF_FILE=${DIFF_DIRECTORY}/diff_before_upgrade_to_master_$(date +"%Y-%m-%d-%H-%M-%S")
mv diff_before_upgrade* ${DIFF_DIRECTORY}/ 2> /dev/null
if ! git diff-index --quiet HEAD; then
echo -e "\e[32mSaving diff to ${DIFF_FILE}...\e[0m"
mkdir -p ${DIFF_DIRECTORY}
git diff ${BRANCH} --stat > ${DIFF_FILE}
git diff ${BRANCH} >> ${DIFF_FILE}
fi
echo -e "\e[32mSwitching Branch to ${BRANCH}...\e[0m"
git fetch origin
git checkout -f ${BRANCH}
elif [ $NEW_BRANCH == "nightly" ] && [ $CURRENT_BRANCH != "nightly" ]; then
echo -e "\e[33mYou are about to switch your mailcow Updates to the unstable (nightly) branch.\e[0m"
sleep 1
echo -e "\e[33mBefore you do: Please take a backup of all components to ensure that no Data is lost...\e[0m"
sleep 1
echo -e "\e[31mWARNING: A switch to nightly is possible any time. But a switch back (to master) isn't.\e[0m"
read -r -p "Are you sure you that want to continue upgrading to the unstable (nightly) branch? [y/N] " response
if [[ ! "${response}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
echo "OK. If you prepared yourself for that please run the update.sh Script with the --nightly parameter again to trigger this process here."
exit 0
fi
BRANCH=$NEW_BRANCH
DIFF_DIRECTORY=update_diffs
DIFF_FILE=${DIFF_DIRECTORY}/diff_before_upgrade_to_nightly_$(date +"%Y-%m-%d-%H-%M-%S")
mv diff_before_upgrade* ${DIFF_DIRECTORY}/ 2> /dev/null
if ! git diff-index --quiet HEAD; then
echo -e "\e[32mSaving diff to ${DIFF_FILE}...\e[0m"
mkdir -p ${DIFF_DIRECTORY}
git diff ${BRANCH} --stat > ${DIFF_FILE}
git diff ${BRANCH} >> ${DIFF_FILE}
fi
git fetch origin
git checkout -f ${BRANCH}
fi
echo -e "\e[32mChecking for newer update script...\e[0m"
SHA1_1=$(sha1sum update.sh)
git fetch origin #${BRANCH}
@@ -683,13 +738,6 @@ if [[ ${SHA1_1} != ${SHA1_2} ]]; then
exit 2
fi
if [[ -f mailcow.conf ]]; then
source mailcow.conf
else
echo -e "\e[31mNo mailcow.conf - is mailcow installed?\e[0m"
exit 1
fi
if [ ! $FORCE ]; then
read -r -p "Are you sure you want to update mailcow: dockerized? All containers will be stopped. [y/N] " response
if [[ ! "${response}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
@@ -699,28 +747,18 @@ if [ ! $FORCE ]; then
migrate_docker_nat
fi
LATEST_COMPOSE=$(curl -#L https://www.servercow.de/docker-compose/latest.php)
COMPOSE_VERSION=$(docker-compose version --short)
if [[ "$LATEST_COMPOSE" != "$COMPOSE_VERSION" ]]; then
echo -e "\e[33mA new docker-compose Version is available: $LATEST_COMPOSE\e[0m"
echo -e "\e[33mYour Version is: $COMPOSE_VERSION\e[0m"
update_compose
else
echo -e "\e[32mYour docker-compose Version is up to date! Not updating it...\e[0m"
fi
remove_obsolete_nginx_ports
echo -e "\e[32mValidating docker-compose stack configuration...\e[0m"
sed -i 's/HTTPS_BIND:-:/HTTPS_BIND:-/g' docker-compose.yml
sed -i 's/HTTP_BIND:-:/HTTP_BIND:-/g' docker-compose.yml
if ! docker-compose config -q; then
if ! $COMPOSE_COMMAND config -q; then
echo -e "\e[31m\nOh no, something went wrong. Please check the error message above.\e[0m"
exit 1
fi
echo -e "\e[32mChecking for conflicting bridges...\e[0m"
MAILCOW_BRIDGE=$(docker-compose config | grep -i com.docker.network.bridge.name | cut -d':' -f2)
MAILCOW_BRIDGE=$($COMPOSE_COMMAND config | grep -i com.docker.network.bridge.name | cut -d':' -f2)
while read NAT_ID; do
iptables -t nat -D POSTROUTING $NAT_ID
done < <(iptables -L -vn -t nat --line-numbers | grep $IPV4_NETWORK | grep -E 'MASQUERADE.*all' | grep -v ${MAILCOW_BRIDGE} | cut -d' ' -f1)
@@ -740,8 +778,8 @@ prefetch_images
echo -e "\e[32mStopping mailcow...\e[0m"
sleep 2
MAILCOW_CONTAINERS=($(docker-compose ps -q))
docker-compose down
MAILCOW_CONTAINERS=($($COMPOSE_COMMAND ps -q))
$COMPOSE_COMMAND down
echo -e "\e[32mChecking for remaining containers...\e[0m"
sleep 2
for container in "${MAILCOW_CONTAINERS[@]}"; do
@@ -778,13 +816,13 @@ elif [[ ${MERGE_RETURN} == 1 ]]; then
elif [[ ${MERGE_RETURN} != 0 ]]; then
echo -e "\e[31m\nOh no, something went wrong. Please check the error message above.\e[0m"
echo
echo "Run docker-compose up -d to restart your stack without updates or try again after fixing the mentioned errors."
echo "Run $COMPOSE_COMMAND up -d to restart your stack without updates or try again after fixing the mentioned errors."
exit 1
fi
echo -e "\e[32mFetching new images, if any...\e[0m"
sleep 2
docker-compose pull
$COMPOSE_COMMAND pull
# Fix missing SSL, does not overwrite existing files
[[ ! -d data/assets/ssl ]] && mkdir -p data/assets/ssl
@@ -796,7 +834,7 @@ if grep -q 'SYSCTL_IPV6_DISABLED=1' mailcow.conf; then
echo '!! IMPORTANT !!'
echo
echo 'SYSCTL_IPV6_DISABLED was removed due to complications. IPv6 can be disabled by editing "docker-compose.yml" and setting "enable_ipv6: true" to "enable_ipv6: false".'
echo 'This setting will only be active after a complete shutdown of mailcow by running "docker-compose down" followed by "docker-compose up -d".'
echo 'This setting will only be active after a complete shutdown of mailcow by running $COMPOSE_COMMAND down followed by $COMPOSE_COMMAND up -d".'
echo
echo '!! IMPORTANT !!'
echo
@@ -824,26 +862,55 @@ if [ -f "data/conf/rspamd/local.d/metrics.conf" ]; then
fi
# Set app_info.inc.php
mailcow_git_version=$(git describe --tags `git rev-list --tags --max-count=1`)
if [ ${BRANCH} == "master" ]; then
mailcow_git_version=$(git describe --tags `git rev-list --tags --max-count=1`)
elif [ ${BRANCH} == "nightly" ]; then
mailcow_git_version=$(git rev-parse --short $(git rev-parse @{upstream}))
mailcow_last_git_version=""
else
mailcow_git_version=$(git rev-parse --short HEAD)
mailcow_last_git_version=""
fi
mailcow_git_commit=$(git rev-parse origin/${BRANCH})
mailcow_git_commit_date=$(git log -1 --format=%ci @{upstream} )
if [ $? -eq 0 ]; then
echo '<?php' > data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_VERSION="'$mailcow_git_version'";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_LAST_GIT_VERSION="";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_OWNER="mailcow";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_REPO="mailcow-dockerized";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_URL="https://github.com/mailcow/mailcow-dockerized";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_COMMIT="'$mailcow_git_commit'";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_COMMIT_DATE="'$mailcow_git_commit_date'";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_BRANCH="'$BRANCH'";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_UPDATEDAT='$(date +%s)';' >> data/web/inc/app_info.inc.php
echo '?>' >> data/web/inc/app_info.inc.php
else
echo '<?php' > data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_VERSION="";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_URL="";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_VERSION="'$mailcow_git_version'";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_LAST_GIT_VERSION="";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_OWNER="mailcow";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_REPO="mailcow-dockerized";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_URL="https://github.com/mailcow/mailcow-dockerized";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_COMMIT="";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_GIT_COMMIT_DATE="";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_BRANCH="'$BRANCH'";' >> data/web/inc/app_info.inc.php
echo ' $MAILCOW_UPDATEDAT='$(date +%s)';' >> data/web/inc/app_info.inc.php
echo '?>' >> data/web/inc/app_info.inc.php
echo -e "\e[33mCannot determine current git repository version...\e[0m"
fi
# Set DOCKER_COMPOSE_VERSION
sed -i 's/^DOCKER_COMPOSE_VERSION=$/DOCKER_COMPOSE_VERSION='$DOCKER_COMPOSE_VERSION'/g' mailcow.conf
if [[ ${SKIP_START} == "y" ]]; then
echo -e "\e[33mNot starting mailcow, please run \"docker-compose up -d --remove-orphans\" to start mailcow.\e[0m"
echo -e "\e[33mNot starting mailcow, please run \"$COMPOSE_COMMAND up -d --remove-orphans\" to start mailcow.\e[0m"
else
echo -e "\e[32mStarting mailcow...\e[0m"
sleep 2
docker-compose up -d --remove-orphans
$COMPOSE_COMMAND up -d --remove-orphans
fi
echo -e "\e[32mCollecting garbage...\e[0m"
@@ -858,4 +925,4 @@ fi
# echo
# git reflog --color=always | grep "Before update on "
# echo
# echo "Use \"git reset --hard hash-on-the-left\" and run docker-compose up -d afterwards."
# echo "Use \"git reset --hard hash-on-the-left\" and run $COMPOSE_COMMAND up -d afterwards."