Roundcube as its own image built by the workflow (no config file or newer Compose needed)
build-container / build (push) Successful in 6m6s
build-container / build (push) Successful in 6m6s
- roundcube/: official Roundcube plus hub.php settings - workflow builds and pushes git.necloud.us/nate/hub-roundcube, and runs the player and webmail tests - compose uses the image instead of an inline config Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
cdf862427e
commit
a7a5b155e3
5 files changed
+67
-49
No files matched your search
@@ -20,6 +20,8 @@ jobs:
|
||||
- run: node tools/smoke-test.js
|
||||
- run: node tools/users-test.js # accounts: private data, tab limits, invites, migration
|
||||
- run: node tools/plex-test.js # Plex sign-in stays signed in and repairs itself
|
||||
- run: node tools/player-test.js # music player: queue, shuffle/repeat, stall recovery
|
||||
- run: node tools/webmail-test.js # the /webmail/ pass-through to Roundcube
|
||||
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
|
||||
@@ -50,3 +52,21 @@ jobs:
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=registry,ref=git.necloud.us/nate/hub:buildcache
|
||||
cache-to: type=registry,ref=git.necloud.us/nate/hub:buildcache,mode=max
|
||||
|
||||
# The webmail container (official Roundcube + the hub's settings)
|
||||
- id: meta_rc
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: git.necloud.us/nate/hub-roundcube
|
||||
tags: |
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
type=sha,format=short
|
||||
type=ref,event=tag
|
||||
|
||||
- uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: ./roundcube
|
||||
platforms: linux/amd64
|
||||
push: true
|
||||
tags: ${{ steps.meta_rc.outputs.tags }}
|
||||
labels: ${{ steps.meta_rc.outputs.labels }}
|
||||
@@ -69,8 +69,8 @@ e.g. hub.necloud.us. Settings: `SEAFILE_URL`, `ONLYOFFICE_URL` env vars in docke
|
||||
authenticated SMTP must be allowed for the mailbox. Then put `M365_CLIENT_ID`, `M365_CLIENT_SECRET`, `M365_TENANT` (the tenant ID) and `PUBLIC_URL`
|
||||
(your hub address, used for the redirect) in `.env` and `docker compose up -d`. The Roundcube login then shows **Login with Microsoft 365**. Microsoft's sign-in
|
||||
page cannot be shown inside a frame, so that one step opens in the whole window and returns you to the Mail tab. Personal Outlook.com accounts are not covered.
|
||||
Roundcube's data (settings, address book, its encryption key) is in the `nehub-roundcube` volume. To change the presets, edit the `roundcube_hub` config in
|
||||
`docker-compose.yml` (needs Docker Compose 2.23.1 or newer). To use a webmail you run elsewhere instead, set `WEBMAIL_URL` (it must allow being framed:
|
||||
Roundcube's data (settings, address book, its encryption key) is in the `nehub-roundcube` volume. The webmail is its own image (`git.necloud.us/nate/hub-roundcube`, built by the Gitea workflow from `roundcube/`: the official Roundcube plus
|
||||
`roundcube/hub.php`), so any compose tool can run it. To change the presets, edit `roundcube/hub.php`. To use a webmail you run elsewhere instead, set `WEBMAIL_URL` (it must allow being framed:
|
||||
no `X-Frame-Options`, and `Content-Security-Policy: frame-ancestors https://<your hub address>`). With neither, Mail is just the shortcut cards.
|
||||
|
||||
roundcube:
|
||||
|
||||
+3
-47
@@ -33,64 +33,20 @@ services:
|
||||
- hub-data:/data # passkeys, calendar links and the session secret live here
|
||||
|
||||
# Webmail shown inside the Mail tab. Only the hub can reach it (no published port), so it sits behind the passkey sign-in.
|
||||
# Sign in to it with your mail address and an app password (Gmail, iCloud and Yahoo are preset in the config below).
|
||||
# Sign in to it with your mail address and an app password (Gmail, iCloud and Yahoo are preset in roundcube/hub.php).
|
||||
roundcube:
|
||||
image: roundcube/roundcubemail:latest-apache
|
||||
image: git.necloud.us/nate/hub-roundcube:latest # built by the Gitea workflow from ./roundcube; `docker compose build` builds locally instead
|
||||
build: ./roundcube
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
ROUNDCUBEMAIL_DB_TYPE: sqlite
|
||||
ROUNDCUBEMAIL_REQUEST_PATH: /webmail/
|
||||
ROUNDCUBEMAIL_PLUGINS: archive,zipdownload
|
||||
ROUNDCUBEMAIL_UPLOAD_MAX_FILESIZE: 30M
|
||||
# Microsoft 365 sign-in (optional, see README -> Mail). Leave empty to skip.
|
||||
M365_CLIENT_ID: ${M365_CLIENT_ID:-}
|
||||
M365_CLIENT_SECRET: ${M365_CLIENT_SECRET:-}
|
||||
M365_TENANT: ${M365_TENANT:-}
|
||||
PUBLIC_URL: ${PUBLIC_URL:-}
|
||||
configs:
|
||||
- source: roundcube_hub
|
||||
target: /var/roundcube/config/hub.php
|
||||
volumes:
|
||||
- roundcube-data:/var/roundcube/db # address book, settings and the encryption key
|
||||
|
||||
configs:
|
||||
roundcube_hub:
|
||||
content: |
|
||||
<?php
|
||||
// Settings for the Roundcube that comes with NE Hub.
|
||||
$$config['product_name'] = 'Mail';
|
||||
$$config['x_frame_options'] = false; // the hub shows this page inside its Mail tab (same address, so only the hub can frame it)
|
||||
$$hosts = [
|
||||
'ssl://imap.gmail.com:993' => 'Gmail',
|
||||
'ssl://imap.mail.me.com:993' => 'iCloud Mail',
|
||||
'ssl://imap.mail.yahoo.com:993' => 'Yahoo Mail',
|
||||
];
|
||||
// Microsoft 365 through OAuth 2.0 (needs an app registration, see README). It goes first because that is where OAuth sign-ins are sent.
|
||||
if (getenv('M365_CLIENT_ID')) {
|
||||
$$hosts = ['ssl://outlook.office365.com:993' => 'Microsoft 365 (use the Microsoft button)'] + $$hosts;
|
||||
$$tenant = getenv('M365_TENANT') ?: 'organizations';
|
||||
$$config['oauth_provider'] = 'generic';
|
||||
$$config['oauth_provider_name'] = 'Microsoft 365';
|
||||
$$config['oauth_client_id'] = getenv('M365_CLIENT_ID');
|
||||
$$config['oauth_client_secret'] = getenv('M365_CLIENT_SECRET');
|
||||
$$config['oauth_auth_uri'] = "https://login.microsoftonline.com/$${tenant}/oauth2/v2.0/authorize";
|
||||
$$config['oauth_token_uri'] = "https://login.microsoftonline.com/$${tenant}/oauth2/v2.0/token";
|
||||
$$config['oauth_identity_uri'] = 'https://graph.microsoft.com/oidc/userinfo';
|
||||
$$config['oauth_identity_fields'] = ['email', 'preferred_username'];
|
||||
$$config['oauth_scope'] = 'email openid profile offline_access https://outlook.office365.com/IMAP.AccessAsUser.All https://outlook.office365.com/SMTP.Send';
|
||||
$$config['oauth_login_redirect'] = false;
|
||||
if (getenv('PUBLIC_URL')) $$config['oauth_redirect_uri'] = rtrim(getenv('PUBLIC_URL'), '/') . '/webmail/index.php/login/oauth';
|
||||
}
|
||||
$$config['imap_host'] = $$hosts;
|
||||
$$config['smtp_host'] = 'tls://smtp.%z:587'; // smtp.gmail.com, smtp.mail.me.com, smtp.mail.yahoo.com
|
||||
$$config['session_lifetime'] = 43200; // minutes (30 days); the hub's own sign-in is what protects access
|
||||
// Behind the hub: believe its forwarded address and https.
|
||||
if (($$_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https') $$_SERVER['HTTPS'] = 'on';
|
||||
if (!empty($$_SERVER['HTTP_X_FORWARDED_HOST'])) $$_SERVER['HTTP_HOST'] = $$_SERVER['HTTP_X_FORWARDED_HOST'];
|
||||
// A fixed encryption key kept with the data, so saved settings and sessions survive restarts and updates.
|
||||
$$kf = '/var/roundcube/db/des_key';
|
||||
if (!is_file($$kf)) @file_put_contents($$kf, bin2hex(random_bytes(12)));
|
||||
if (is_file($$kf)) $$config['des_key'] = trim(file_get_contents($$kf));
|
||||
volumes:
|
||||
hub-data:
|
||||
name: nehub-data # fixed name so the data survives redeploys and renamed stacks
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# Roundcube webmail for NE Hub: the official image plus the hub's settings (so no config file has to be mounted).
|
||||
FROM roundcube/roundcubemail:latest-apache
|
||||
COPY hub.php /var/roundcube/config/hub.php
|
||||
ENV ROUNDCUBEMAIL_DB_TYPE=sqlite \
|
||||
ROUNDCUBEMAIL_REQUEST_PATH=/webmail/ \
|
||||
ROUNDCUBEMAIL_PLUGINS=archive,zipdownload \
|
||||
ROUNDCUBEMAIL_UPLOAD_MAX_FILESIZE=30M
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
// Settings for the Roundcube that comes with NE Hub.
|
||||
$config['product_name'] = 'Mail';
|
||||
$config['x_frame_options'] = false; // the hub shows this page inside its Mail tab (same address, so only the hub can frame it)
|
||||
$hosts = [
|
||||
'ssl://imap.gmail.com:993' => 'Gmail',
|
||||
'ssl://imap.mail.me.com:993' => 'iCloud Mail',
|
||||
'ssl://imap.mail.yahoo.com:993' => 'Yahoo Mail',
|
||||
];
|
||||
// Microsoft 365 through OAuth 2.0 (needs an app registration, see README). It goes first because that is where OAuth sign-ins are sent.
|
||||
if (getenv('M365_CLIENT_ID')) {
|
||||
$hosts = ['ssl://outlook.office365.com:993' => 'Microsoft 365 (use the Microsoft button)'] + $hosts;
|
||||
$tenant = getenv('M365_TENANT') ?: 'organizations';
|
||||
$config['oauth_provider'] = 'generic';
|
||||
$config['oauth_provider_name'] = 'Microsoft 365';
|
||||
$config['oauth_client_id'] = getenv('M365_CLIENT_ID');
|
||||
$config['oauth_client_secret'] = getenv('M365_CLIENT_SECRET');
|
||||
$config['oauth_auth_uri'] = "https://login.microsoftonline.com/${tenant}/oauth2/v2.0/authorize";
|
||||
$config['oauth_token_uri'] = "https://login.microsoftonline.com/${tenant}/oauth2/v2.0/token";
|
||||
$config['oauth_identity_uri'] = 'https://graph.microsoft.com/oidc/userinfo';
|
||||
$config['oauth_identity_fields'] = ['email', 'preferred_username'];
|
||||
$config['oauth_scope'] = 'email openid profile offline_access https://outlook.office365.com/IMAP.AccessAsUser.All https://outlook.office365.com/SMTP.Send';
|
||||
$config['oauth_login_redirect'] = false;
|
||||
if (getenv('PUBLIC_URL')) $config['oauth_redirect_uri'] = rtrim(getenv('PUBLIC_URL'), '/') . '/webmail/index.php/login/oauth';
|
||||
}
|
||||
$config['imap_host'] = $hosts;
|
||||
$config['smtp_host'] = 'tls://smtp.%z:587'; // smtp.gmail.com, smtp.mail.me.com, smtp.mail.yahoo.com
|
||||
$config['session_lifetime'] = 43200; // minutes (30 days); the hub's own sign-in is what protects access
|
||||
// Behind the hub: believe its forwarded address and https.
|
||||
if (($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https') $_SERVER['HTTPS'] = 'on';
|
||||
if (!empty($_SERVER['HTTP_X_FORWARDED_HOST'])) $_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
|
||||
// A fixed encryption key kept with the data, so saved settings and sessions survive restarts and updates.
|
||||
$kf = '/var/roundcube/db/des_key';
|
||||
if (!is_file($kf)) @file_put_contents($kf, bin2hex(random_bytes(12)));
|
||||
if (is_file($kf)) $config['des_key'] = trim(file_get_contents($kf));
|
||||
Reference in new issue
Block a user