Server Config Locking
LuCLI can lock server configuration per environment so that future lucli server start and lucli server run commands use a stable, reproducible configuration even if lucee.json changes.
This is built on top of lucee-lock.json, which is already the source of truth for dependency locking.
Concepts
-
Per-environment locks
- Locks are stored under a
serverLockssection inlucee-lock.json. - Each entry is keyed by an "environment key":
_default– used when no--env/--environmentflag is passed.- Named envs such as
prod,dev,staging, etc.
- Each lock stores:
- Whether it is active (
locked: true|false). - The config file name (usually
lucee.json). - A hash of the config file at lock time.
- The fully realized
ServerConfigthat LuCLI will use when starting servers.
- Whether it is active (
- Locks are stored under a
-
Lenient runtime behaviour
- Locked configuration never prevents a server from starting.
- If a lock is present for the requested env, LuCLI uses the locked
effectiveConfigsnapshot. - If
lucee.jsonhas changed since the lock was created, LuCLI logs a warning explaining that the project is locked and that the live file differs from the locked snapshot.
-
Mutation guard
lucli server config setrefuses to writelucee.jsonwhen any environment is locked, unless you use--dry-run.- This keeps
lucee.jsonandlucee-lock.jsonin sync by forcing you to unlock or explicitly update the lock.
CLI commands
Locking configuration
# Lock default (no-env) configuration for the current project directory
lucli server lock
# Lock configuration for a specific environment
lucli server lock --env=prod
# Lock using a custom config file
lucli server lock --config=lucee-static.json
# Refresh an existing lock from the current lucee.json
lucli server lock --env=prod --update
Semantics:
lucli server lock(no--env) locks the effective configuration for the default environment under the_defaultkey.lucli server lock --env=prodlocks the effective configuration that would be used for--env=prod.--updatereplaces an existing lock entry with a new snapshot from the currentlucee.json.- When locking, any
${secret:NAME}placeholders inlucee.json/CFConfig are resolved once and the resolved values are stored in the locked snapshot. This ensures future starts under that lock do not depend on being able to open the secret store at runtime.
If a lock is already active for that environment and you do not pass --update, LuCLI will print a helpful error explaining that the env is already locked and how to update or unlock it.
Unlocking configuration
# Unlock default (no-env) configuration
lucli server unlock
# Unlock a specific environment
lucli server unlock --env=prod
Unlocking:
- Marks that environment as unlocked in
lucee-lock.json. - Does not stop any running servers; it only affects future
server start/runcommands.
Effect on server start / run
When you start a server, LuceeServerManager looks for a matching lock entry before loading lucee.json:
-
Determine environment key:
_defaultwhen no--env/--environmentwas specified.- The value of
--env/--environmentotherwise.
-
Load
lucee-lock.jsonfrom the project directory. -
If there is an active lock for that env (
locked: trueand aneffectiveConfig), LuCLI:- Uses the locked
effectiveConfigsnapshot as the server configuration. - Compares the current config file (
lucee.jsonby default) to the storedconfigHash. - If the hash is different, prints a warning similar to:
⚠️ Server configuration is LOCKED for env 'prod' (lucee-lock.json) - Using locked configuration snapshot - Detected changes in lucee.json since the lock was created (hash mismatch) - To roll these changes into the lock: lucli server lock --env=prod --update - To remove the lock: lucli server unlock --env=prod - Uses the locked
-
If there is no active lock for that env, LuCLI behaves as before:
- Loads
lucee.json. - Applies any
--envenvironment overrides. - Starts the server from the live configuration.
- Loads
Important notes
- Locks are per environment, not per server name.
- A lock only affects the configuration resolution step; all other behaviour (port conflict checks, Tomcat generation, CFConfig, extension deployment) remains the same.
- Because runtime behaviour is lenient, a locked project will still start successfully even if someone has edited
lucee.json; the warning explains why the new values were not applied.
Effect on server config set
server config set writes directly to lucee.json. When any environment is locked, LuCLI:
- Still allows
--dry-runto preview what would be written. - Refuses to write the file without
--dry-runand prints a message like:
❌ Cannot modify lucee.json via 'server config set' because server configuration is LOCKED.
Locked environments: _default, prod
To change configuration:
- Unlock: lucli server unlock --env=<env>
- Or update lock: lucli server lock --env=<env> --update
This makes it explicit that lucee-lock.json is the source of truth for locked environments.
Typical workflows
1. Locking production configuration
# Validate config for production
lucli server start --env=prod --dry-run
# Lock production configuration
lucli server lock --env=prod
# Start a production server later
lucli server start --env=prod
Even if a developer later edits lucee.json, the production starts will continue to use the locked configuration, with a warning about drift.
2. Updating a lock after editing lucee.json
# Edit lucee.json (change ports, HTTPS, etc.)
vi lucee.json
# Preview the effect
lucli server start --env=prod --dry-run
# Refresh the lock from the new configuration
lucli server lock --env=prod --update
# Start with updated locked config
lucli server start --env=prod
3. Temporarily changing config in development
# Project is locked for default env
lucli server lock
# You want to experiment with different ports locally
lucli server unlock
lucli server config set port=8085
lucli server start
# Once you are happy with the new config, re-lock it
lucli server lock --update
Autocompletion hints
The interactive terminal completion now includes:
server lockandserver unlockas subcommands.- Emojis for lock/unlock in completion lists when emojis are enabled.
You can type server l<Tab> or server u<Tab> to quickly access these commands in terminal mode.