ESCTL provides a containerized deployment path using Docker and Docker Compose, allowing you to quickly spin up the entire software stack including the controller, database, and identity provider.
Architecture
The following diagram illustrates how the Docker containers interact with each other and the physical hardware nodes.
Component Overview
The Docker environment consists of several interconnected services:
- Controller (
esctl/controller): The main controller servicing esctl nodes. - Database (
mariadb): Stores system logs and access events. - Identity Provider (
esctl/openldap): Manages users, groups, and security tokens. - LDAP Admin (
phpldapadmin): A web-based interface for managing the LDAP directory.
Getting Started
The Docker orchestration files are located in server/trunk/docker/esctl/.
1. Configuration
Before starting the services, you must create a .env file from the provided template:
cd server/trunk/docker/esctl/
cp .env.template .env
Edit the .env file to set your specific passwords, domain names, and database names.
2. Launching the Stack
Use Docker Compose to build (if necessary) and start all containers in the background:
docker compose up -d
3. Custom LDAP Seeding (Optional)
On first run, the OpenLDAP container (esctl/openldap) automatically loads the core schema (70esctl.ldif) and mounts initial seed data from server/trunk/docker/openldap/samples/. To seed custom users, groups, or tokens on initialization, place .ldif files into server/trunk/docker/openldap/samples/.
Environment Variables
The controller container is highly configurable via environment variables. Key variables include:
| Variable | Description | Default |
|---|---|---|
| Database Settings | ||
ESCTL_DB_HOST |
Hostname of the database container/service. | db |
ESCTL_DB_NAME |
Name of the MySQL/MariaDB database. | esctl |
ESCTL_DB_USER |
Username for logging database connection. | root |
ESCTL_DB_PASS |
Password for logging database connection. | mysqlsecret |
| LDAP Settings | ||
ESCTL_LDAP_SERVER |
URL of the LDAP server (can be a JSON-like array for multiple servers). | ldap://ldap/ |
ESCTL_LDAP_GROUP_SEARCH_TYPE |
LDAP search strategy (simple or AD). |
simple |
ESCTL_LDAP_BASE_DN |
Base Distinguished Name for searches. | dc=example,dc=hosted,dc=esctl,dc=co,dc=uk |
ESCTL_LDAP_USER |
Bind DN to authenticate connections to LDAP. | cn=admin,${ESCTL_LDAP_BASE_DN} |
ESCTL_LDAP_PASSWORD |
Bind password for LDAP authentication. | esctlsecret |
ESCTL_LDAP_GROUPS_DN |
Base DN containing groups. | ou=Groups,${ESCTL_LDAP_BASE_DN} |
ESCTL_LDAP_TOKENS_DN |
Base DN containing security token mappings. | ou=tokens,ou=esctl,${ESCTL_LDAP_BASE_DN} |
ESCTL_LDAP_READERS_DN |
Base DN containing door reader specifications. | ou=readers,ou=esctl,${ESCTL_LDAP_BASE_DN} |
| Hardware & Protocol Settings | ||
ESCTL_SITE_DEFAULT_DOOROPENTIME |
Duration in seconds to unlock the door upon access approval. | 3 |
ESCTL_SITE_DEFAULT_FORMAT |
Card reader token format prefix (e.g. WG). |
WG |
ESCTL_CHAR_READ_TIMEOUT |
Timeout in seconds between characters for reader connection socket. | 0.050 |
ESCTL_KEEPALIVE_ABORT_COUNT |
Number of missed keepalives before resetting connection. | 3 |
| Token Security & Hashing | ||
ESCTL_TOKEN_HASH_TYPES |
Supported token hashing algorithms (none, sha256, sha512). |
["sha512", "none"] |
ESCTL_TOKEN_HASH_SECRET |
Salt string used for generating secure token hashes. | MyTopS3cr3tT3xtStr1ng |
| Logging, Debugging & Profiling | ||
ESCTL_DEBUG |
syslog debug log verbosity level (0 to 15). | 1 |
ESCTL_DEBUG_PROFILER |
Enables high-resolution timing/profiling logs (0 = disabled, 1 = enabled to STDERR). |
0 |
ESCTL_ERROR_LOG |
Target path inside container for stderr/error log redirection. | /var/log/esctl_errors |
TZ |
Container timezone setting for time calculations and access scheduling (inherits host TZ if set, defaulting to Europe/London). |
${TZ:-Europe/London} |
| IPC Semaphores | ||
ESCTL_SEMAPHORE_PATH |
Directory path for IPC semaphore files. | /tmp/esctl |
ESCTL_SEMAPHORE_MODE |
Octal file mode permissions for semaphore directory. | 03770 |
Advanced Building
If you are building the controller image from source, the Dockerfile supports multi-stage builds and requires git credentials to perform a sparse checkout of the repository.
You can set BUILD_GIT_PASSWORD in your .env file:
BUILD_GIT_USERNAME=yourhostname-build
BUILD_GIT_PASSWORD=your_git_password
Alternatively, pass BUILD_GIT_PASSWORD directly when running docker compose up --build:
# Build and launch with git password
BUILD_GIT_PASSWORD=mypass docker compose up --build -d
Or build using docker compose build:
# Build with custom build args directly
docker compose build --build-arg BUILD_GIT_USERNAME=myuser --build-arg BUILD_GIT_PASSWORD=mypass
Monitoring & Logs
You can monitor the output of the controller and other services using standard Docker commands:
docker compose logs -f controller
The controller also redirects error logs to /var/log/esctl_errors inside the container by default.
[!NOTE] Timezone Handling in Logs: The controller container automatically inherits the host machine’s timezone via
TZ=${TZ:-Europe/London}(or can be explicitly overridden in.env). All application decision logic, schedule calculations, and database entries execute in local time. Note that Docker container log streams (docker compose logs) and syslog packet transport headers emit timestamps in UTC/Zulu time per standard container logging specifications.
Automated Integration Testing
The Docker deployment includes a 100% automated integration test suite written in Perl TAP (Test::More).
To launch the container stack and execute all integration tests:
cd server/trunk/tests
./run-tests.sh
See Integration Testing and the code documentation in server/trunk/tests/README.md for full details.