Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions dev2/sites.d/webmail.profullstack.com.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"service": "webmail.profullstack.com",
"repo": null,
"branch": null,
"image": "roundcube/roundcubemail:1.7.5-apache",
"image": "profullstack/webmail:1.7.5-cal1",
"start_command": "apache2-foreground",
"port_var": "80",
"domains": [
Expand Down Expand Up @@ -48,9 +48,9 @@
"ROUNDCUBEMAIL_DEFAULT_PORT": "993",
"ROUNDCUBEMAIL_SMTP_SERVER": "ssl://smtp.forwardemail.net",
"ROUNDCUBEMAIL_SMTP_PORT": "465",
"ROUNDCUBEMAIL_PLUGINS": "anyhost,archive,zipdownload",
"ROUNDCUBEMAIL_PLUGINS": "anyhost,archive,zipdownload,libcalendaring,libkolab,calendar,tasklist,carddav",
"ROUNDCUBEMAIL_SKIN": "elastic",
"ROUNDCUBEMAIL_UPLOAD_MAX_FILESIZE": "25M"
},
"notes": "Not a Railway site: born on dev2 2026-11-02. Primary host webmail.profullstack.com (A -> dev2); webmail.pit.world kept as an alias. Cert by HTTP-01 (both names resolve to dev2). Roundcube webmail, stock image, no repo. Login form has a Server field: users sign in to ANY IMAP server (blank = Forward Email, imap.forwardemail.net). The anyhost plugin (cli-tools dev2/webmail/anyhost, copied to volumes/plugin-anyhost) turns a bare hostname into ssl://host:993, derives SMTP (imap.X -> smtp.X, else the same host; 465 then 587) and refuses private/loopback addresses so the form cannot probe dev2. volumes/config/zz-profullstack.inc.php holds des_key (minted on the box, never committed) and the imap_host override. mail.profullstack.com is NOT this site: it is the bbs box's Mailu MTA (PTR, SPF, cert)."
"notes": "Not a Railway site: born on dev2 2026-11-02. Primary host webmail.profullstack.com (A -> dev2); webmail.pit.world kept as an alias. Cert by HTTP-01 (both names resolve to dev2). Roundcube webmail, stock image, no repo. Login form has a Server field: users sign in to ANY IMAP server (blank = Forward Email, imap.forwardemail.net). The anyhost plugin (cli-tools dev2/webmail/anyhost, copied to volumes/plugin-anyhost) turns a bare hostname into ssl://host:993, derives SMTP (imap.X -> smtp.X, else the same host; 465 then 587) and refuses private/loopback addresses so the form cannot probe dev2. volumes/config/zz-profullstack.inc.php holds des_key (minted on the box, never committed) and the imap_host override. mail.profullstack.com is NOT this site: it is the bbs box's Mailu MTA (PTR, SPF, cert). Since 2026-11-02 the image is profullstack/webmail:<tag>, built ON dev2 from cli-tools dev2/webmail/Dockerfile (docker build -t profullstack/webmail:<tag> dev2/webmail; not on any registry, deploy pull fails harmlessly): stock 1.7.5 + Kolab calendar/tasklist 3.6.1 + RCMCardDAV 5.1.5. FE sessions sync caldav.forwardemail.net / carddav.forwardemail.net; other servers get database calendars. Plugin schemas loaded once into volumes/db with bin/updatedb.sh."
}
24 changes: 24 additions & 0 deletions dev2/webmail/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# webmail.profullstack.com: stock Roundcube + calendar/tasks (Kolab, CalDAV) + contacts (RCMCardDAV).
# Built on dev2 as profullstack/webmail:<tag> (see README.md); the entrypoint copies
# /usr/src/roundcubemail into /var/www/html on every fresh container.
FROM roundcube/roundcubemail:1.7.5-apache

# libkolab pins pear/http_request2 ~2.5.0, which is under CVE-2025-43717 (XSS, fixed
# 2.7.0); composer blocks it. Install the fixed 2.8.0 aliased as 2.5.1 instead of
# ignoring the advisory.

# roundcube/plugin-installer runs each plugin's SQL on install; there is no database at
# build time (SKIP_DB_INIT). The live schema is created on the box (README.md).
RUN cd /usr/src/roundcubemail \
&& SKIP_DB_INIT=1 SKIP_DB_UPDATE=1 COMPOSER_ALLOW_SUPERUSER=1 composer require --no-interaction --no-progress --update-no-dev --prefer-dist \
"pear/http_request2:2.8.0 as 2.5.1" \
kolab/calendar:3.6.1 kolab/tasklist:3.6.1 roundcube/carddav:5.1.5 \
&& ls plugins

# libkolab 3.6.1 sqlite.initial.sql creates ix_contact_type twice (kolab_cache_contact and
# kolab_cache_dav_contact); SQLite index names are per database, so init fails.
RUN sed -i 's/^CREATE INDEX ix_contact_type ON kolab_cache_dav_contact/CREATE INDEX ix_dav_contact_type ON kolab_cache_dav_contact/' \
/usr/src/roundcubemail/plugins/libkolab/SQL/sqlite.initial.sql \
&& grep -c ix_dav_contact_type /usr/src/roundcubemail/plugins/libkolab/SQL/sqlite.initial.sql

COPY --chmod=644 carddav.config.inc.php /usr/src/roundcubemail/plugins/carddav/config.inc.php
22 changes: 22 additions & 0 deletions dev2/webmail/anyhost/anyhost.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,28 @@ public function init()
$this->add_hook('authenticate', [$this, 'authenticate']);
$this->add_hook('smtp_connect', [$this, 'smtp_connect']);
$this->add_hook('template_object_loginform', [$this, 'loginform']);
// calendar/tasklist load their own config.inc.php in init() (after this plugin) and
// pick their driver in startup; our startup hook is registered first, so it wins.
$this->add_hook('startup', function ($args) { $this->pick_dav_drivers(); return $args; });
}

/**
* Calendar + tasks backend for this session (anyhost loads before calendar/tasklist,
* so this runs first): Forward Email users sync with caldav.forwardemail.net; every
* other server gets Roundcube's own database calendar (Mailu has no CalDAV).
*/
private function pick_dav_drivers()
{
$config = rcmail::get_instance()->config;
if ((string) ($_SESSION['storage_host'] ?? '') === 'imap.forwardemail.net') {
$config->set('calendar_driver', 'caldav');
$config->set('calendar_caldav_server', 'https://caldav.forwardemail.net');
$config->set('tasklist_driver', 'caldav');
$config->set('tasklist_caldav_server', 'https://caldav.forwardemail.net');
} else {
$config->set('calendar_driver', 'database');
$config->set('tasklist_driver', 'database');
}
}

public function loginform($args)
Expand Down
20 changes: 20 additions & 0 deletions dev2/webmail/carddav.config.inc.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php
// RCMCardDAV presets for webmail.profullstack.com.
// The login form takes any IMAP server, so the Forward Email address book is only
// set up for sessions signed in to imap.forwardemail.net. Everyone else can still
// add an address book by hand in Settings > CardDAV.
$prefs['_GLOBAL']['pwstore_scheme'] = 'des_key';
$prefs['_GLOBAL']['loglevel'] = \Psr\Log\LogLevel::WARNING;

if ((string) ($_SESSION['storage_host'] ?? '') === 'imap.forwardemail.net') {
$prefs['forwardemail'] = [
'accountname' => 'Forward Email',
'discovery_url' => 'https://carddav.forwardemail.net/dav/',
'username' => '%u',
'password' => '%p',
'fixed' => ['discovery_url', 'username', 'password'],
'refresh_time' => '00:15:00',
'active' => true,
'readonly' => false,
];
}
Loading