2026-09-07 21:00:49 +03:00
2026-09-07 21:00:49 +03:00
2026-08-31 21:32:58 +03:00
2026-09-07 21:00:49 +03:00

Eternity Roundcube Skin

Eternity is a sharp editorial skin for Roundcube, built in the visual language of Eternity Project: paper-white surfaces, ink-black structure, acid-green actions, and orange signals. It extends Roundcube's maintained Elastic skin, retaining Elastic's responsive layout and interaction model while changing the visual treatment.

Requirements

  • Roundcube 1.6.x
  • The bundled elastic skin must remain installed
  • A web server able to serve static CSS files from Roundcube's skins directory

The skin has no build step and no PHP dependencies. Its font stacks use Space Grotesk and DM Mono when those fonts are available, then fall back to locally installed system fonts. This keeps the login screen usable without a third-party font request.

Install

  1. Copy the eternity directory into the Roundcube installation's skins directory:

    cp -R eternity /var/www/roundcube/skins/
    
  2. Ensure the web-server user can read the copied files:

    chown -R www-data:www-data /var/www/roundcube/skins/eternity
    find /var/www/roundcube/skins/eternity -type d -exec chmod 755 {} \;
    find /var/www/roundcube/skins/eternity -type f -exec chmod 644 {} \;
    
  3. Set the default skin in Roundcube's configuration. Add or update this line in config/config.inc.php:

    $config['skin'] = 'eternity';
    
  4. Clear the browser cache, then load Roundcube. The login view, mailbox list, compose view, menus, controls, and status messages should all use the new palette.

Docker Install

Docker Compose (persistent)

Place this repository alongside the Compose file, then bind-mount the skin into the Roundcube service. The official roundcube/roundcubemail image exposes its application at /var/www/html.

services:
  roundcube:
	 volumes:
		- ./ep-roundcube-skin/eternity:/var/www/html/skins/eternity:ro
		- ./roundcube-config/config.inc.php:/var/roundcube/config/config.inc.php:ro

Create ./roundcube-config/config.inc.php if it does not already exist and include the skin setting with the rest of the deployment configuration:

<?php

$config['skin'] = 'eternity';

The configuration mount location can vary for non-official images. Check the image documentation or run docker compose exec roundcube sh -c 'find / -path "*/config.inc.php" 2>/dev/null' to identify the active configuration file. Restart the service after changing either mount:

docker compose up -d --force-recreate roundcube

Existing Running Container

Use this method to test the skin on a container that is already running. Replace roundcube with the container name or ID shown by docker ps.

  1. Copy the skin from this repository into the container:

    docker cp ./eternity roundcube:/var/www/html/skins/eternity
    
  2. Confirm Roundcube can see the skin files:

    docker exec roundcube sh -c 'test -f /var/www/html/skins/eternity/meta.json && test -f /var/www/html/skins/eternity/styles/styles.css'
    
  3. Add $config['skin'] = 'eternity'; to the active config.inc.php in the container, then restart it:

    docker restart roundcube
    

This live-container approach is not persistent: docker compose up --force-recreate, docker rm, or an image update removes the copied skin and in-container configuration change. Once the skin is confirmed, add the two bind mounts from the Compose example so both survive container recreation.

After either deployment method, hard-refresh the browser or clear its cache. If the old appearance remains, inspect the browser network panel to confirm that /skins/eternity/styles/styles.css returns HTTP 200.

If instead the page looks entirely unstyled — login credential fields stacked in the wrong place, an oversized logo, or mailbox toolbars/tabs scattered and hard to read — styles/styles.css is loading but its @import of ../../elastic/styles/styles.css is not, so none of Elastic's layout rules apply. Confirm that file exists and is readable:

docker exec roundcube sh -c 'test -f /var/www/html/skins/elastic/styles/styles.css && echo FOUND || echo MISSING'

If it is MISSING, the Elastic skin was installed from source without its LESS files being compiled (Elastic ships as .less sources and requires make css-elastic / bin/updatecss.sh to produce styles/styles.css). Reinstall Elastic from an official Roundcube release tarball, which ships the compiled CSS, rather than a bare git checkout.

Verify A Running Container

Run these commands on the Docker host, replacing roundcube with the container name or ID from docker ps. They distinguish an installation issue from an activation issue:

docker exec roundcube sh -c 'for file in /var/www/html/skins/eternity/meta.json /var/www/html/skins/eternity/styles/styles.css /var/www/html/skins/elastic/styles/styles.css; do test -f "$file" && echo "FOUND $file" || echo "MISSING $file"; done'
docker exec roundcube sh -c 'grep -RIn "\$config\[.skin.\]" /var/roundcube/config /var/www/html/config 2>/dev/null || true'

The first command must report all three paths as FOUND. The second must show eternity as the configured skin. On the official image, the equivalent persistent environment setting is:

environment:
	ROUNDCUBEMAIL_SKIN: eternity

Roundcube can store a skin preference for each user. A user who previously selected another appearance may continue to receive that preference instead of the newly configured default. Sign out and test in a private browser window or select Eternity from Roundcube's Settings > Preferences > User Interface > Interface skin, when the preference is available.

For a browser-level check, open this URL directly, replacing the hostname with the Roundcube site:

https://webmail.example.com/skins/eternity/styles/styles.css

It must return CSS beginning with @import url("../../elastic/styles/styles.css");. A 404 means the skin is not mounted at the path served by the container. If it returns 200 but Roundcube still looks unchanged, inspect the mailbox page source: it must include a stylesheet URL containing /skins/eternity/styles/styles.css. If it instead contains /skins/elastic/, the active configuration or the user's stored preference still selects Elastic.

Structure

eternity/
  meta.json          Skin registration and Elastic inheritance
  styles/styles.css  Visual overrides for Elastic

styles/styles.css imports Elastic before applying Eternity's overrides. Do not remove the import: the base skin provides the complete component layout and image assets.

Customize

The visual palette is declared at the top of eternity/styles/styles.css:

Token Value Role
--ink #11212b Primary text, borders, and primary controls
--paper #f1f1e9 Page and surface background
--acid #c7ef4b Primary hover, selection, and success state
--orange #ff6b35 Links, secondary hover, quota, and error signal
--line #b9c5bc Quiet dividers
--muted #59706b Secondary text

Change these variables to retheme the interface while preserving the semantic states. Test login, inbox, compose, contacts, settings, search, and mobile navigation after any update to Roundcube or Elastic.

Upgrade Notes

This is an Elastic child skin. When updating Roundcube, keep the eternity directory in place and confirm that the upstream Elastic stylesheet remains at skins/elastic/styles/styles.css. Recopy the skin after deployments that replace the whole Roundcube skins directory.

The skin intentionally uses direct CSS selectors for stable Roundcube surfaces and CSS custom properties for broad Elastic integration. If a future Roundcube release renames markup, inspect that release's Elastic stylesheet and update the matching override selector here.

License

Licensed under the GNU Affero General Public License, version 3 or later. See LICENSE.

S
Description
No description provided
Readme
108 KiB
Languages
CSS 72.3%
HTML 27.7%