commit
bdba65686b
|
@ -8,10 +8,9 @@ while mysqladmin ping --host mysql --silent; do
|
|||
mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DROP VIEW IF EXISTS sogo_view"
|
||||
|
||||
mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
||||
CREATE VIEW sogo_view (c_uid, domain, c_name, c_password, c_cn, mail, aliases, ad_aliases, senderacl, home, kind, multiple_bookings) AS
|
||||
SELECT mailbox.username, mailbox.domain, mailbox.username, mailbox.password, mailbox.name, mailbox.username, IFNULL(ga.aliases, ''), IFNULL(gda.ad_alias, ''), IFNULL(gs.send_as, ''), CONCAT('/var/vmail/', maildir), mailbox.kind, mailbox.multiple_bookings FROM mailbox
|
||||
CREATE VIEW sogo_view (c_uid, domain, c_name, c_password, c_cn, mail, aliases, ad_aliases, home, kind, multiple_bookings) AS
|
||||
SELECT mailbox.username, mailbox.domain, mailbox.username, mailbox.password, mailbox.name, mailbox.username, IFNULL(ga.aliases, ''), IFNULL(gda.ad_alias, ''), CONCAT('/var/vmail/', maildir), mailbox.kind, mailbox.multiple_bookings FROM mailbox
|
||||
LEFT OUTER JOIN grouped_mail_aliases ga ON ga.username = mailbox.username
|
||||
LEFT OUTER JOIN grouped_sender_acl gs ON gs.username = mailbox.username
|
||||
LEFT OUTER JOIN grouped_domain_alias_address gda ON gda.username = mailbox.username
|
||||
WHERE mailbox.active = '1';
|
||||
EOF
|
||||
|
@ -50,11 +49,10 @@ EOF
|
|||
# Generate multi-domain setup
|
||||
while read line
|
||||
do
|
||||
DOMAIN_SANE=$(echo ${line} | tr '-' 'b' | tr '.' 'p' | tr -cd '[[:alnum:]]')
|
||||
echo " <key>${line}</key>
|
||||
<dict>
|
||||
<key>SOGoMailDomain</key>
|
||||
<string>${DOMAIN_SANE}</string>
|
||||
<string>${line}</string>
|
||||
<key>SOGoUserSources</key>
|
||||
<array>
|
||||
<dict>
|
||||
|
@ -62,7 +60,6 @@ while read line
|
|||
<array>
|
||||
<string>aliases</string>
|
||||
<string>ad_aliases</string>
|
||||
<string>senderacl</string>
|
||||
</array>
|
||||
<key>KindFieldName</key>
|
||||
<string>kind</string>
|
||||
|
@ -98,4 +95,4 @@ chmod 600 /var/lib/sogo/GNUstep/Defaults/sogod.plist
|
|||
|
||||
sleep 99999
|
||||
|
||||
done;
|
||||
done
|
||||
|
|
|
@ -39,7 +39,7 @@ server {
|
|||
|
||||
rewrite ^(/save.+)$ /rspamd$1 last;
|
||||
location /rspamd/ {
|
||||
proxy_pass http://rspamd:11334/;
|
||||
proxy_pass http://172.22.1.253:11334/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
|
||||
|
@ -61,7 +61,7 @@ server {
|
|||
}
|
||||
|
||||
location ^~ /Microsoft-Server-ActiveSync {
|
||||
proxy_pass http://sogo:20000/SOGo/Microsoft-Server-ActiveSync;
|
||||
proxy_pass http://172.22.1.252:20000/SOGo/Microsoft-Server-ActiveSync;
|
||||
proxy_connect_timeout 1000;
|
||||
proxy_next_upstream timeout error;
|
||||
proxy_send_timeout 1000;
|
||||
|
@ -83,7 +83,7 @@ server {
|
|||
}
|
||||
|
||||
location ^~ /SOGo {
|
||||
proxy_pass http://sogo:20000;
|
||||
proxy_pass http://172.22.1.252:20000;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $host;
|
||||
|
@ -105,7 +105,7 @@ server {
|
|||
}
|
||||
|
||||
location /SOGo.woa/WebServerResources/ {
|
||||
proxy_pass http://sogo:9192/WebServerResources/;
|
||||
proxy_pass http://172.22.1.252:9192/WebServerResources/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache sogo;
|
||||
proxy_cache_valid 200 1d;
|
||||
|
@ -115,7 +115,7 @@ server {
|
|||
}
|
||||
|
||||
location /SOGo/WebServerResources/ {
|
||||
proxy_pass http://sogo:9192/WebServerResources/;
|
||||
proxy_pass http://172.22.1.252:9192/WebServerResources/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache sogo;
|
||||
proxy_cache_valid 200 1d;
|
||||
|
@ -125,7 +125,7 @@ server {
|
|||
}
|
||||
|
||||
location (^/SOGo/so/ControlPanel/Products/[^/]*UI/Resources/.*\.(jpg|png|gif|css|js)$ {
|
||||
proxy_pass http://sogo:9192/$1.SOGo/Resources/$2;
|
||||
proxy_pass http://172.22.1.252:9192/$1.SOGo/Resources/$2;
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache sogo;
|
||||
proxy_cache_valid 200 1d;
|
||||
|
|
|
@ -14,4 +14,9 @@ $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|||
while ($row = array_shift($rows)) {
|
||||
echo strtolower(trim($row['username'])) . PHP_EOL;
|
||||
}
|
||||
$stmt = $pdo->query("SELECT CONCAT(mailbox.local_part, '@', alias_domain.alias_domain) as `tag_ad` FROM `mailbox` INNER JOIN `alias_domain` ON mailbox.domain = alias_domain.target_domain WHERE mailbox.wants_tagged_subject='1';");
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
while ($row = array_shift($rows)) {
|
||||
echo strtolower(trim($row['tag_ad'])) . PHP_EOL;
|
||||
}
|
||||
?>
|
|
@ -27,11 +27,25 @@ rspamd_config.ADD_DELIMITER_TAG = {
|
|||
callback = function(task)
|
||||
local util = require("rspamd_util")
|
||||
local rspamd_logger = require "rspamd_logger"
|
||||
local user_tagged = task:get_recipients(1)[1]['user']
|
||||
|
||||
local user_env_tagged = task:get_recipients(1)[1]['user']
|
||||
local user_to_tagged = task:get_recipients(2)[1]['user']
|
||||
|
||||
local domain = task:get_recipients(1)[1]['domain']
|
||||
local user, tag = user_tagged:match("([^+]+)+(.*)")
|
||||
|
||||
local user_env, tag_env = user_env_tagged:match("([^+]+)+(.*)")
|
||||
local user_to, tag_to = user_to_tagged:match("([^+]+)+(.*)")
|
||||
|
||||
local authdomain = auth_domain_map:get_key(domain)
|
||||
|
||||
if tag_env then
|
||||
tag = tag_env
|
||||
user = user_env
|
||||
elseif tag_to then
|
||||
tag = tag_to
|
||||
user = user_env
|
||||
end
|
||||
|
||||
if tag and authdomain then
|
||||
rspamd_logger.infox("Domain %s is part of mailcow, start reading tag settings", domain)
|
||||
local user_untagged = user .. '@' .. domain
|
||||
|
@ -40,12 +54,12 @@ rspamd_config.ADD_DELIMITER_TAG = {
|
|||
rspamd_logger.infox("User wants subject modified for tagged mail")
|
||||
local sbj = task:get_header('Subject')
|
||||
if tag then
|
||||
rspamd_logger.infox("Found tag %1, will modify subject header", tag)
|
||||
new_sbj = '=?UTF-8?B?' .. tostring(util.encode_base64('[' .. tag .. '] ' .. sbj)) .. '?='
|
||||
task:set_rmilter_reply({
|
||||
remove_headers = {['Subject'] = 1},
|
||||
add_headers = {['Subject'] = new_sbj}
|
||||
})
|
||||
rspamd_logger.infox("Found tag %1, will modify subject header", tag)
|
||||
new_sbj = '=?UTF-8?B?' .. tostring(util.encode_base64('[' .. tag .. '] ' .. sbj)) .. '?='
|
||||
task:set_rmilter_reply({
|
||||
remove_headers = {['Subject'] = 1},
|
||||
add_headers = {['Subject'] = new_sbj}
|
||||
})
|
||||
end
|
||||
else
|
||||
rspamd_logger.infox("Add X-Moo-Tag header")
|
||||
|
|
|
@ -4,6 +4,7 @@ require_once("inc/prerequisites.inc.php");
|
|||
if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admin") {
|
||||
require_once("inc/header.inc.php");
|
||||
$_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
||||
$tfa_data = get_tfa();
|
||||
?>
|
||||
<div class="container">
|
||||
<h4><span class="glyphicon glyphicon-user" aria-hidden="true"></span> <?=$lang['admin']['access'];?></h4>
|
||||
|
@ -43,12 +44,26 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
|||
<div class="row">
|
||||
<div class="col-sm-3 col-xs-5 text-right"><?=$lang['tfa']['tfa'];?>:</div>
|
||||
<div class="col-sm-9 col-xs-7">
|
||||
<p><?=get_tfa()['pretty'];?></p>
|
||||
<p id="tfa_pretty"><?=$tfa_data['pretty'];?></p>
|
||||
<div id="tfa_additional">
|
||||
<?php if($tfa_data['additional']):
|
||||
foreach ($tfa_data['additional'] as $key_info): ?>
|
||||
<form style="display:inline;" method="post">
|
||||
<input type="hidden" name="unset_tfa_key" value="<?=$key_info['id'];?>" />
|
||||
<div style="padding:4px;margin:4px" class="label label-<?=($_SESSION['tfa_id'] == $key_info['id']) ? 'success' : 'default'; ?>">
|
||||
<?=$key_info['key_id'];?>
|
||||
<a href="#" style="font-weight:bold;color:white" onClick="$(this).closest('form').submit()">[<?=strtolower($lang['admin']['remove']);?>]</a>
|
||||
</div>
|
||||
</form>
|
||||
<?php endforeach;
|
||||
endif;?>
|
||||
</div>
|
||||
<br />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-xs-5 text-right"><?=$lang['tfa']['set_tfa'];?>:</div>
|
||||
<div class="col-md-9 col-xs-7">
|
||||
<div class="col-sm-3 col-xs-5 text-right"><?=$lang['tfa']['set_tfa'];?>:</div>
|
||||
<div class="col-sm-9 col-xs-7">
|
||||
<select data-width="auto" id="selectTFA" class="selectpicker" title="<?=$lang['tfa']['select'];?>">
|
||||
<option value="yubi_otp"><?=$lang['tfa']['yubi_otp'];?></option>
|
||||
<option value="u2f"><?=$lang['tfa']['u2f'];?></option>
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
<?php
|
||||
require_once 'inc/vars.inc.php';
|
||||
|
||||
ini_set('error_reporting', '0');
|
||||
$config = array(
|
||||
'useEASforOutlook' => 'yes',
|
||||
|
@ -31,7 +29,7 @@ if ($config['useEASforOutlook'] == 'no') {
|
|||
$config['autodiscoverType'] = 'imap';
|
||||
}
|
||||
}
|
||||
require_once 'inc/functions.inc.php';
|
||||
|
||||
$dsn = "$database_type:host=$database_host;dbname=$database_name";
|
||||
$opt = [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
|
|
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
|
@ -114,7 +114,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
|||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" name="delete_tfa"> <?=$lang['tfa']['delete_tfa'];?></label>
|
||||
<label><input type="checkbox" name="disable_tfa"> <?=$lang['tfa']['disable_tfa'];?></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -24,9 +24,9 @@ endif;
|
|||
?>
|
||||
<div style="margin-bottom:100px"></div>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-switch/3.3.2/js/bootstrap-switch.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/7.0.2/bootstrap-slider.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.9.4/js/bootstrap-select.js"></script>
|
||||
<script src="/js/bootstrap-switch.min.js"></script>
|
||||
<script src="/js/bootstrap-slider.min.js"></script>
|
||||
<script src="/js/bootstrap-select.min.js"></script>
|
||||
<script src="/js/u2f-api.js"></script>
|
||||
<script>
|
||||
// Select language and reopen active URL without POST
|
||||
|
@ -74,6 +74,7 @@ $(document).ready(function() {
|
|||
<?php endif; ?>
|
||||
|
||||
// Set TFA modals
|
||||
|
||||
$('#selectTFA').change(function () {
|
||||
if ($(this).val() == "yubi_otp") {
|
||||
$('#YubiOTPModal').modal('show');
|
||||
|
|
|
@ -63,6 +63,7 @@ function hasMailboxObjectAccess($username, $role, $object) {
|
|||
return false;
|
||||
}
|
||||
function init_db_schema() {
|
||||
// This will be much better in future releases...
|
||||
global $pdo;
|
||||
try {
|
||||
$stmt = $pdo->prepare("SELECT NULL FROM `admin`, `imapsync`, `tfa`");
|
||||
|
@ -101,7 +102,7 @@ function init_db_schema() {
|
|||
$stmt = $pdo->query("SHOW COLUMNS FROM `mailbox` LIKE 'kind'");
|
||||
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
if ($num_results == 0) {
|
||||
$pdo->query("ALTER TABLE `mailbox` ADD `kind` varchar(100) NOT NULL DEFAULT ''");
|
||||
$pdo->query("ALTER TABLE `mailbox` ADD `kind` VARCHAR(100) NOT NULL DEFAULT ''");
|
||||
}
|
||||
$stmt = $pdo->query("SHOW COLUMNS FROM `mailbox` LIKE 'multiple_bookings'");
|
||||
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
|
@ -113,6 +114,11 @@ function init_db_schema() {
|
|||
if ($num_results == 0) {
|
||||
$pdo->query("ALTER TABLE `mailbox` ADD `wants_tagged_subject` tinyint(1) NOT NULL DEFAULT '0'");
|
||||
}
|
||||
$stmt = $pdo->query("SHOW COLUMNS FROM `tfa` LIKE 'key_id'");
|
||||
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
if ($num_results == 0) {
|
||||
$pdo->query("ALTER TABLE `tfa` ADD `key_id` VARCHAR(255) DEFAULT 'unidentified'");
|
||||
}
|
||||
}
|
||||
function verify_ssha256($hash, $password) {
|
||||
// Remove tag if any
|
||||
|
@ -198,6 +204,8 @@ function check_login($user, $pass) {
|
|||
}
|
||||
else {
|
||||
unset($_SESSION['ldelay']);
|
||||
$stmt = $pdo->prepare("UPDATE `tfa` SET `active`='1' WHERE `username` = :user");
|
||||
$stmt->execute(array(':user' => $user));
|
||||
return "domainadmin";
|
||||
}
|
||||
}
|
||||
|
@ -1806,6 +1814,10 @@ function set_tfa($postarray) {
|
|||
|
||||
switch ($postarray["tfa_method"]) {
|
||||
case "yubi_otp":
|
||||
(!isset($postarray["key_id"])) ? $key_id = 'unidentified' : $key_id = $postarray["key_id"];
|
||||
$yubico_id = $postarray['yubico_id'];
|
||||
$yubico_key = $postarray['yubico_key'];
|
||||
$yubi = new Auth_Yubico($yubico_id, $yubico_key);
|
||||
if (!$yubi) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
|
@ -1824,16 +1836,21 @@ function set_tfa($postarray) {
|
|||
if (PEAR::isError($yauth)) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'Yubico Authentication error: ' . $yauth->getMessage()
|
||||
'msg' => 'Yubico API: ' . $yauth->getMessage()
|
||||
);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare("DELETE FROM `tfa` WHERE `authmech` = 'yubi_otp' AND `username` = :username");
|
||||
$stmt->execute(array(':username' => $username));
|
||||
$stmt = $pdo->prepare("INSERT INTO `tfa` (`username`, `authmech`, `active`) VALUES
|
||||
(:username, 'yubi_otp', 1)");
|
||||
$stmt->execute(array(':username' => $username));
|
||||
// We could also do a modhex translation here
|
||||
$yubico_modhex_id = substr($postarray["otp_token"], 0, 12);
|
||||
$stmt = $pdo->prepare("DELETE FROM `tfa`
|
||||
WHERE `username` = :username
|
||||
AND (`authmech` != 'yubi_otp')
|
||||
OR (`authmech` = 'yubi_otp' AND `secret` LIKE :modhex)");
|
||||
$stmt->execute(array(':username' => $username, ':modhex' => '%' . $yubico_modhex_id));
|
||||
$stmt = $pdo->prepare("INSERT INTO `tfa` (`key_id`, `username`, `authmech`, `active`, `secret`) VALUES
|
||||
(:key_id, :username, 'yubi_otp', '1', :secret)");
|
||||
$stmt->execute(array(':key_id' => $key_id, ':username' => $username, ':secret' => $yubico_id . ':' . $yubico_key . ':' . $yubico_modhex_id));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'] = array(
|
||||
|
@ -1850,9 +1867,12 @@ function set_tfa($postarray) {
|
|||
|
||||
case "u2f":
|
||||
try {
|
||||
(!isset($postarray["key_id"])) ? $key_id = 'unidentified' : $key_id = $postarray["key_id"];
|
||||
$reg = $u2f->doRegister(json_decode($_SESSION['regReq']), json_decode($postarray['token']));
|
||||
$stmt = $pdo->prepare("INSERT INTO `tfa` (`username`, `authmech`, `keyHandle`, `publicKey`, `certificate`, `counter`) VALUES (?, 'u2f', ?, ?, ?, ?)");
|
||||
$stmt->execute(array($username, $reg->keyHandle, $reg->publicKey, $reg->certificate, $reg->counter));
|
||||
$stmt = $pdo->prepare("DELETE FROM `tfa` WHERE `username` = :username AND `authmech` != 'u2f'");
|
||||
$stmt->execute(array(':username' => $username));
|
||||
$stmt = $pdo->prepare("INSERT INTO `tfa` (`username`, `key_id`, `authmech`, `keyHandle`, `publicKey`, `certificate`, `counter`, `active`) VALUES (?, ?, 'u2f', ?, ?, ?, ?, '1')");
|
||||
$stmt->execute(array($username, $key_id, $reg->keyHandle, $reg->publicKey, $reg->certificate, $reg->counter));
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'success',
|
||||
'msg' => sprintf($lang['success']['object_modified'], $username)
|
||||
|
@ -1887,6 +1907,55 @@ function set_tfa($postarray) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
function unset_tfa_key($postarray) {
|
||||
// Can only unset own keys
|
||||
// Needs at least one key left
|
||||
global $pdo;
|
||||
global $lang;
|
||||
$id = intval($postarray['unset_tfa_key']);
|
||||
if ($_SESSION['mailcow_cc_role'] != "domainadmin" &&
|
||||
$_SESSION['mailcow_cc_role'] != "admin") {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => sprintf($lang['danger']['access_denied'])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$username = $_SESSION['mailcow_cc_username'];
|
||||
try {
|
||||
if (!is_numeric($id)) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => sprintf($lang['danger']['access_denied'])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$stmt = $pdo->prepare("SELECT COUNT(*) AS `keys` FROM `tfa`
|
||||
WHERE `username` = :username AND `active` = '1'");
|
||||
$stmt->execute(array(':username' => $username));
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if ($row['keys'] == "1") {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => sprintf($lang['danger']['last_key'])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$stmt = $pdo->prepare("DELETE FROM `tfa` WHERE `username` = :username AND `id` = :id");
|
||||
$stmt->execute(array(':username' => $username, ':id' => $id));
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'success',
|
||||
'msg' => sprintf($lang['success']['object_modified'], $username)
|
||||
);
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'MySQL: '.$e
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function get_tfa($username = null) {
|
||||
global $pdo;
|
||||
if (isset($_SESSION['mailcow_cc_username'])) {
|
||||
|
@ -1896,8 +1965,8 @@ function get_tfa($username = null) {
|
|||
return false;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("SELECT `authmech` FROM `tfa`
|
||||
WHERE `username` = :username");
|
||||
$stmt = $pdo->prepare("SELECT * FROM `tfa`
|
||||
WHERE `username` = :username AND `active` = '1'");
|
||||
$stmt->execute(array(':username' => $username));
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
|
@ -1905,11 +1974,27 @@ function get_tfa($username = null) {
|
|||
case "yubi_otp":
|
||||
$data['name'] = "yubi_otp";
|
||||
$data['pretty'] = "Yubico OTP";
|
||||
$stmt = $pdo->prepare("SELECT `id`, `key_id`, RIGHT(`secret`, 12) AS 'modhex' FROM `tfa` WHERE `authmech` = 'yubi_otp' AND `username` = :username");
|
||||
$stmt->execute(array(
|
||||
':username' => $username,
|
||||
));
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
while($row = array_shift($rows)) {
|
||||
$data['additional'][] = $row;
|
||||
}
|
||||
return $data;
|
||||
break;
|
||||
case "u2f":
|
||||
$data['name'] = "u2f";
|
||||
$data['pretty'] = "Fido U2F";
|
||||
$stmt = $pdo->prepare("SELECT `id`, `key_id` FROM `tfa` WHERE `authmech` = 'u2f' AND `username` = :username");
|
||||
$stmt->execute(array(
|
||||
':username' => $username,
|
||||
));
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
while($row = array_shift($rows)) {
|
||||
$data['additional'][] = $row;
|
||||
}
|
||||
return $data;
|
||||
break;
|
||||
case "hotp":
|
||||
|
@ -1935,7 +2020,7 @@ function verify_tfa_login($username, $token) {
|
|||
global $yubi;
|
||||
|
||||
$stmt = $pdo->prepare("SELECT `authmech` FROM `tfa`
|
||||
WHERE `username` = :username");
|
||||
WHERE `username` = :username AND `active` = '1'");
|
||||
$stmt->execute(array(':username' => $username));
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
|
@ -1944,6 +2029,16 @@ function verify_tfa_login($username, $token) {
|
|||
if (!ctype_alnum($token) || strlen($token) != 44) {
|
||||
return false;
|
||||
}
|
||||
$yubico_modhex_id = substr($token, 0, 12);
|
||||
$stmt = $pdo->prepare("SELECT `id`, `secret` FROM `tfa`
|
||||
WHERE `username` = :username
|
||||
AND `authmech` = 'yubi_otp'
|
||||
AND `active`='1'
|
||||
AND `secret` LIKE :modhex");
|
||||
$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]);
|
||||
$yauth = $yubi->verify($token);
|
||||
if (PEAR::isError($yauth)) {
|
||||
$_SESSION['return'] = array(
|
||||
|
@ -1953,6 +2048,7 @@ function verify_tfa_login($username, $token) {
|
|||
return false;
|
||||
}
|
||||
else {
|
||||
$_SESSION['tfa_id'] = $row['id'];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1963,6 +2059,7 @@ function verify_tfa_login($username, $token) {
|
|||
$reg = $u2f->doAuthenticate(json_decode($_SESSION['authReq']), get_u2f_registrations($username), json_decode($token));
|
||||
$stmt = $pdo->prepare("UPDATE `tfa` SET `counter` = ? WHERE `id` = ?");
|
||||
$stmt->execute(array($reg->counter, $reg->id));
|
||||
$_SESSION['tfa_id'] = $reg->id;
|
||||
$_SESSION['authReq'] = null;
|
||||
return true;
|
||||
}
|
||||
|
@ -2089,8 +2186,8 @@ function edit_domain_admin($postarray) {
|
|||
':modified' => date('Y-m-d H:i:s'),
|
||||
':active' => $active
|
||||
));
|
||||
if (isset($postarray['delete_tfa'])) {
|
||||
$stmt = $pdo->prepare("DELETE FROM `tfa` WHERE `username` = :username");
|
||||
if (isset($postarray['disable_tfa'])) {
|
||||
$stmt = $pdo->prepare("UPDATE `tfa` SET `active` = '0' WHERE `username` = :username");
|
||||
$stmt->execute(array(':username' => $username_now));
|
||||
}
|
||||
else {
|
||||
|
@ -2115,8 +2212,8 @@ function edit_domain_admin($postarray) {
|
|||
':modified' => date('Y-m-d H:i:s'),
|
||||
':active' => $active
|
||||
));
|
||||
if (isset($postarray['delete_tfa'])) {
|
||||
$stmt = $pdo->prepare("DELETE FROM `tfa` WHERE `username` = :username");
|
||||
if (isset($postarray['disable_tfa'])) {
|
||||
$stmt = $pdo->prepare("UPDATE `tfa` SET `active` = '0' WHERE `username` = :username");
|
||||
$stmt->execute(array(':username' => $username));
|
||||
}
|
||||
else {
|
||||
|
@ -4818,23 +4915,8 @@ function mailbox_get_sender_acl_handles($mailbox) {
|
|||
}
|
||||
function get_u2f_registrations($username) {
|
||||
global $pdo;
|
||||
$sel = $pdo->prepare("SELECT * FROM `tfa` WHERE `username` = ?");
|
||||
$sel = $pdo->prepare("SELECT * FROM `tfa` WHERE `authmech` = 'u2f' AND `username` = ? AND `active` = '1'");
|
||||
$sel->execute(array($username));
|
||||
return $sel->fetchAll(PDO::FETCH_OBJ);
|
||||
}
|
||||
function add_u2f_registration($username, $reg) {
|
||||
global $pdo;
|
||||
global $lang;
|
||||
$ins = $pdo->prepare("INSERT INTO `tfa` (`username`, `authmech`, `keyHandle`, `publicKey`, `certificate`, `counter`) VALUES (?, 'u2f', ?, ?, ?, ?)");
|
||||
$ins->execute(array($username, $reg->keyHandle, $reg->publicKey, $reg->certificate, $reg->counter));
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'success',
|
||||
'msg' => sprintf($lang['success']['object_modified'], $username)
|
||||
);
|
||||
}
|
||||
function edit_u2f_registration($reg) {
|
||||
global $pdo;
|
||||
$upd = $pdo->prepare("update tfa set counter = ? where id = ?");
|
||||
$upd->execute(array($reg->counter, $reg->id));
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.0/jquery.min.js" integrity="sha384-XxcvoeNF5V0ZfksTnV+bejnCsJjOOIzN6UVwF85WBsAnU3zeYh5bloN+L4WLgeNE" crossorigin="anonymous"></script>
|
||||
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootswatch/3.3.6/<?=strtolower(trim($DEFAULT_THEME));?>/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.9.4/css/bootstrap-select.min.css">
|
||||
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/7.0.2/css/bootstrap-slider.min.css">
|
||||
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootstrap-switch/3.3.2/css/bootstrap3/bootstrap-switch.min.css">
|
||||
<link rel="stylesheet" href="/css/bootstrap-select.min.css">
|
||||
<link rel="stylesheet" href="/css/bootstrap-slider.min.css">
|
||||
<link rel="stylesheet" href="/css/bootstrap-switch.min.css">
|
||||
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Source+Sans+Pro:400,600,700&subset=latin,latin-ext">
|
||||
<link rel="stylesheet" href="/inc/languages.min.css">
|
||||
<link rel="stylesheet" href="/css/mailcow.css">
|
||||
|
@ -45,6 +45,7 @@
|
|||
<ul class="dropdown-menu" role="menu">
|
||||
<li <?=($_SESSION['mailcow_locale'] == 'de') ? 'class="active"' : ''?>> <a href="?<?= http_build_query(array_merge($_GET, array("lang" => "de"))) ?>"><span class="lang-xs lang-lbl-full" lang="de"></span></a></li>
|
||||
<li <?=($_SESSION['mailcow_locale'] == 'en') ? 'class="active"' : ''?>> <a href="?<?= http_build_query(array_merge($_GET, array("lang" => "en"))) ?>"><span class="lang-xs lang-lbl-full" lang="en"></span></a></li>
|
||||
<li <?=($_SESSION['mailcow_locale'] == 'es') ? 'class="active"' : ''?>> <a href="?<?= http_build_query(array_merge($_GET, array("lang" => "es"))) ?>"><span class="lang-xs lang-lbl-full" lang="es"></span></a></li>
|
||||
<li <?=($_SESSION['mailcow_locale'] == 'nl') ? 'class="active"' : ''?>> <a href="?<?= http_build_query(array_merge($_GET, array("lang" => "nl"))) ?>"><span class="lang-xs lang-lbl-full" lang="nl"></span></a></li>
|
||||
<li <?=($_SESSION['mailcow_locale'] == 'pt') ? 'class="active"' : ''?>> <a href="?<?= http_build_query(array_merge($_GET, array("lang" => "pt"))) ?>"><span class="lang-xs lang-lbl-full" lang="pt"></span></a></li>
|
||||
</ul>
|
||||
|
|
|
@ -22,10 +22,8 @@ if (file_exists('./inc/vars.local.inc.php')) {
|
|||
}
|
||||
|
||||
// Yubi OTP API
|
||||
if (!empty($YUBI_API['ID']) && !empty($YUBI_API['KEY'])) {
|
||||
require_once 'inc/lib/Yubico.php';
|
||||
$yubi = new Auth_Yubico($YUBI_API['ID'], $YUBI_API['KEY']);
|
||||
}
|
||||
require_once 'inc/lib/Yubico.php';
|
||||
|
||||
// U2F API
|
||||
require_once 'inc/lib/U2F.php';
|
||||
$scheme = isset($_SERVER['HTTPS']) ? "https://" : "http://";
|
||||
|
@ -59,6 +57,10 @@ if (isset($_COOKIE['language'])) {
|
|||
$_SESSION['mailcow_locale'] = 'en';
|
||||
setcookie('language', 'en');
|
||||
break;
|
||||
case "es":
|
||||
$_SESSION['mailcow_locale'] = 'es';
|
||||
setcookie('language', 'es');
|
||||
break;
|
||||
case "nl":
|
||||
$_SESSION['mailcow_locale'] = 'nl';
|
||||
setcookie('language', 'nl');
|
||||
|
@ -79,6 +81,10 @@ if (isset($_GET['lang'])) {
|
|||
$_SESSION['mailcow_locale'] = 'en';
|
||||
setcookie('language', 'en');
|
||||
break;
|
||||
case "es":
|
||||
$_SESSION['mailcow_locale'] = 'es';
|
||||
setcookie('language', 'es');
|
||||
break;
|
||||
case "nl":
|
||||
$_SESSION['mailcow_locale'] = 'nl';
|
||||
setcookie('language', 'nl');
|
||||
|
|
|
@ -4,6 +4,18 @@
|
|||
<div class="modal-header"><b><?=$lang['tfa']['yubi_otp'];?></b></div>
|
||||
<div class="modal-body">
|
||||
<form role="form" method="post">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="key_id" id="key_id" placeholder="<?=$lang['tfa']['key_id'];?>" autocomplete="off" required>
|
||||
</div>
|
||||
<hr>
|
||||
<p class="help-block"><?=$lang['tfa']['api_register'];?></p>
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="yubico_id" id="yubico_id" placeholder="Yubico API ID" autocomplete="off" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="yubico_key" id="yubico_key" placeholder="Yubico API Key" autocomplete="off" required>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="form-group">
|
||||
<input type="password" class="form-control" name="confirm_password" id="confirm_password" placeholder="<?=$lang['user']['password_now'];?>" autocomplete="off" required>
|
||||
</div>
|
||||
|
@ -27,6 +39,9 @@
|
|||
<div class="modal-header"><b><?=$lang['tfa']['u2f'];?></b></div>
|
||||
<div class="modal-body">
|
||||
<form role="form" method="post" id="u2f_reg_form">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="key_id" id="key_id" placeholder="<?=$lang['tfa']['key_id'];?>" autocomplete="off" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="password" class="form-control" name="confirm_password" id="confirm_password" placeholder="<?=$lang['user']['password_now'];?>" autocomplete="off" required>
|
||||
</div>
|
||||
|
|
|
@ -115,6 +115,9 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
|||
if (isset($_POST["set_tfa"])) {
|
||||
set_tfa($_POST);
|
||||
}
|
||||
if (isset($_POST["unset_tfa_key"])) {
|
||||
unset_tfa_key($_POST);
|
||||
}
|
||||
if (isset($_POST["add_policy_list_item"])) {
|
||||
add_policy_list_item($_POST);
|
||||
}
|
||||
|
|
|
@ -35,8 +35,4 @@ $DEFAULT_LANG = "en";
|
|||
// See https://bootswatch.com/
|
||||
$DEFAULT_THEME = "lumen";
|
||||
|
||||
// If you want to use Yubico TFA methods, setup an ID and a key here: https://upgrade.yubico.com/getapikey/
|
||||
// Remember to override this value using vars.local.inc.php, do not change it here.
|
||||
$YUBI_API['ID'] = "";
|
||||
$YUBI_API['KEY'] = "";
|
||||
?>
|
||||
|
|
|
@ -48,6 +48,7 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
|||
<ul class="dropdown-menu">
|
||||
<li <?=($_SESSION['mailcow_locale'] == 'de') ? 'class="active"' : ''?>><a href="?<?= http_build_query(array_merge($_GET, array("lang" => "de"))) ?>"><span class="lang-xs lang-lbl-full" lang="de"></span></a></li>
|
||||
<li <?=($_SESSION['mailcow_locale'] == 'en') ? 'class="active"' : ''?>><a href="?<?= http_build_query(array_merge($_GET, array("lang" => "en"))) ?>"><span class="lang-xs lang-lbl-full" lang="en"></span></a></li>
|
||||
<li <?=($_SESSION['mailcow_locale'] == 'es') ? 'class="active"' : ''?>><a href="?<?= http_build_query(array_merge($_GET, array("lang" => "es"))) ?>"><span class="lang-xs lang-lbl-full" lang="es"></span></a></li>
|
||||
<li <?=($_SESSION['mailcow_locale'] == 'nl') ? 'class="active"' : ''?>><a href="?<?= http_build_query(array_merge($_GET, array("lang" => "nl"))) ?>"><span class="lang-xs lang-lbl-full" lang="nl"></span></a></li>
|
||||
<li <?=($_SESSION['mailcow_locale'] == 'pt') ? 'class="active"' : ''?>><a href="?<?= http_build_query(array_merge($_GET, array("lang" => "pt"))) ?>"><span class="lang-xs lang-lbl-full" lang="pt"></span></a></li>
|
||||
</ul>
|
||||
|
|
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
|
@ -29,6 +29,7 @@ $lang['danger']['policy_list_from_exists'] = 'Ein Eintrag mit diesem Wert existi
|
|||
$lang['danger']['policy_list_from_invalid'] = 'Eintrag hat ungültiges Format';
|
||||
$lang['danger']['alias_invalid'] = 'Alias-Adrese ist ungültig';
|
||||
$lang['danger']['goto_invalid'] = 'Ziel-Adrese ist ungültig';
|
||||
$lang['danger']['last_key'] = 'Letzter Key kann nicht gelöscht werden';
|
||||
$lang['danger']['alias_domain_invalid'] = 'Alias-Domain ist ungültig';
|
||||
$lang['danger']['target_domain_invalid'] = 'Ziel-Domain ist ungültig';
|
||||
$lang['danger']['object_exists'] = 'Objekt %s existiert bereits';
|
||||
|
@ -374,11 +375,14 @@ $lang['login']['delayed'] = 'Login wurde zur Sicherheit um %s Sekunde/n verzöge
|
|||
$lang['tfa']['tfa'] = "Two-Factor Authentication";
|
||||
$lang['tfa']['set_tfa'] = "Konfiguriere Two-Factor Authentication Methode";
|
||||
$lang['tfa']['yubi_otp'] = "Yubico OTP Authentifizierung";
|
||||
$lang['tfa']['key_id'] = "Ein Name für diesen YubiKey";
|
||||
$lang['tfa']['api_register'] = 'mailcow verwendet die Yubico Cloud API. Ein API-Key für den Yubico Stick kann <a href="https://upgrade.yubico.com/getapikey/" target="_blank">hier</a> bezogen werden.';
|
||||
$lang['tfa']['u2f'] = "U2F Authentifizierung";
|
||||
$lang['tfa']['hotp'] = "HOTP Authentifizierung";
|
||||
$lang['tfa']['totp'] = "TOTP Authentifizierung";
|
||||
$lang['tfa']['none'] = "Deaktiviert";
|
||||
$lang['tfa']['delete_tfa'] = "Deaktiviere TFA";
|
||||
$lang['tfa']['disable_tfa'] = "Deaktiviere TFA bis zur nächsten erfolgreichen Anmeldung";
|
||||
$lang['tfa']['confirm_tfa'] = "Please confirm your one-time password in the below field";
|
||||
$lang['tfa']['confirm'] = "Bestätigen";
|
||||
$lang['tfa']['otp'] = "Einmalpasswort";
|
||||
|
|
|
@ -24,6 +24,7 @@ $lang['danger']['mailbox_quota_exceeds_domain_quota'] = "Max. quota exceeds doma
|
|||
$lang['danger']['object_is_not_numeric'] = "Value %s is not numeric";
|
||||
$lang['success']['domain_added'] = "Added domain %s";
|
||||
$lang['danger']['alias_empty'] = "Alias address must not be empty";
|
||||
$lang['danger']['last_key'] = 'Last key cannot be deleted';
|
||||
$lang['danger']['goto_empty'] = "Goto address must not be empty";
|
||||
$lang['danger']['policy_list_from_exists'] = "A record with given name exists";
|
||||
$lang['danger']['policy_list_from_invalid'] = "Record has invalid format";
|
||||
|
@ -377,11 +378,14 @@ $lang['login']['delayed'] = 'Login was delayed by %s seconds.';
|
|||
$lang['tfa']['tfa'] = "Two-factor authentication";
|
||||
$lang['tfa']['set_tfa'] = "Set two-factor authentication method";
|
||||
$lang['tfa']['yubi_otp'] = "Yubico OTP authentication";
|
||||
$lang['tfa']['key_id'] = "An identifier for your YubiKey";
|
||||
$lang['tfa']['api_register'] = 'mailcow uses the Yubico Cloud API. Please get an API key for your key <a href="https://upgrade.yubico.com/getapikey/" target="_blank">here</a>';
|
||||
$lang['tfa']['u2f'] = "U2F authentication";
|
||||
$lang['tfa']['hotp'] = "HOTP authentication";
|
||||
$lang['tfa']['totp'] = "TOTP authentication";
|
||||
$lang['tfa']['none'] = "Deaktiviert";
|
||||
$lang['tfa']['delete_tfa'] = "Disable TFA";
|
||||
$lang['tfa']['disable_tfa'] = "Disable TFA until next successful login";
|
||||
$lang['tfa']['confirm_tfa'] = "Please confirm your one-time password in the below field";
|
||||
$lang['tfa']['confirm'] = "Confirm";
|
||||
$lang['tfa']['otp'] = "One-time password";
|
||||
|
|
|
@ -8,6 +8,7 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'doma
|
|||
|
||||
require_once("inc/header.inc.php");
|
||||
$_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
||||
$tfa_data = get_tfa();
|
||||
$username = $_SESSION['mailcow_cc_username'];
|
||||
?>
|
||||
<div class="container">
|
||||
|
@ -23,15 +24,27 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'doma
|
|||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-xs-5 text-right"><?=$lang['tfa']['tfa'];?></div>
|
||||
<div class="col-md-9 col-xs-7">
|
||||
<p><?=get_tfa()['pretty'];?></p>
|
||||
</div>
|
||||
<div class="col-sm-9 col-xs-7">
|
||||
<p id="tfa_pretty"><?=$tfa_data['pretty'];?></p>
|
||||
<div id="tfa_additional">
|
||||
<?php if($tfa_data['additional']):
|
||||
foreach ($tfa_data['additional'] as $key_info): ?>
|
||||
<form style="display:inline;" method="post">
|
||||
<input type="hidden" name="unset_tfa_key" value="<?=$key_info['id'];?>" />
|
||||
<div class="label label-default">🔑 <?=$key_info['key_id'];?> <a href="#" style="font-weight:bold;color:white" onClick="$(this).closest('form').submit()">[<?=strtolower($lang['admin']['remove']);?>]</a></div>
|
||||
</form>
|
||||
<?php endforeach;
|
||||
endif;?>
|
||||
</div>
|
||||
<br />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-xs-5 text-right"><?=$lang['tfa']['set_tfa'];?></div>
|
||||
<div class="col-md-9 col-xs-7">
|
||||
<select id="selectTFA" class="selectpicker" title="<?=$lang['tfa']['select'];?>">
|
||||
<option value="yubi_otp"><?=$lang['tfa']['yubi_otp'];?></option>
|
||||
<option value="u2f"><?=$lang['tfa']['u2f'];?></option>
|
||||
<option value="none"><?=$lang['tfa']['none'];?></option>
|
||||
</select>
|
||||
</div>
|
||||
|
|
|
@ -3,6 +3,9 @@ version: '2.1'
|
|||
services:
|
||||
pdns-mailcow:
|
||||
image: andryyy/mailcow-dockerized:pdns
|
||||
depends_on:
|
||||
mysql-mailcow:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ./data/conf/pdns/:/etc/powerdns/
|
||||
restart: always
|
||||
|
@ -14,9 +17,11 @@ services:
|
|||
|
||||
mysql-mailcow:
|
||||
image: mariadb:10.1
|
||||
depends_on:
|
||||
- pdns-mailcow
|
||||
command: mysqld
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "--host", "localhost", "--silent"]
|
||||
interval: 10s
|
||||
timeout: 30s
|
||||
retries: 5
|
||||
volumes:
|
||||
- mysql-vol-1:/var/lib/mysql/
|
||||
- ./data/conf/mysql/:/etc/mysql/conf.d/:ro
|
||||
|
@ -52,7 +57,7 @@ services:
|
|||
rspamd-mailcow:
|
||||
image: andryyy/mailcow-dockerized:rspamd
|
||||
depends_on:
|
||||
- pdns-mailcow
|
||||
- nginx-mailcow
|
||||
volumes:
|
||||
- ./data/conf/rspamd/override.d/:/etc/rspamd/override.d:ro
|
||||
- ./data/conf/rspamd/local.d/:/etc/rspamd/local.d:ro
|
||||
|
@ -65,6 +70,7 @@ services:
|
|||
dns_search: mailcow-network
|
||||
networks:
|
||||
mailcow-network:
|
||||
ipv4_address: 172.22.1.253
|
||||
aliases:
|
||||
- rspamd
|
||||
|
||||
|
@ -95,7 +101,6 @@ services:
|
|||
image: andryyy/mailcow-dockerized:sogo
|
||||
depends_on:
|
||||
- pdns-mailcow
|
||||
- mysql-mailcow
|
||||
environment:
|
||||
- DBNAME=${DBNAME}
|
||||
- DBUSER=${DBUSER}
|
||||
|
@ -110,6 +115,7 @@ services:
|
|||
restart: always
|
||||
networks:
|
||||
mailcow-network:
|
||||
ipv4_address: 172.22.1.252
|
||||
aliases:
|
||||
- sogo
|
||||
|
||||
|
@ -197,10 +203,8 @@ services:
|
|||
|
||||
nginx-mailcow:
|
||||
depends_on:
|
||||
- mysql-mailcow
|
||||
- sogo-mailcow
|
||||
- php-fpm-mailcow
|
||||
- rspamd-mailcow
|
||||
image: nginx:mainline
|
||||
command: /bin/bash -c "envsubst < /etc/nginx/conf.d/listen.template > /etc/nginx/conf.d/listen.active && nginx -g 'daemon off;'"
|
||||
environment:
|
||||
|
|
Loading…
Reference in New Issue