Skip to main content
uses a Self-hosted Daemon (also called the Modelcode Daemon) to execute build, run, and test commands on your own infrastructure. This is necessary when your project depends on private services — such as internal APIs, databases, or package registries — that are not accessible from the public internet.

When to Use a Self-hosted Daemon

Use a Self-hosted Daemon when your project requires access to:
  • Private package registries — NPM, PyPi, or Maven registries hosted behind a VPN or firewall
  • Internal APIs or microservices — Services that your application calls during startup or testing
  • Private databases — Database instances that are only reachable from your internal network
  • On-premise infrastructure — Any resource that cannot reach from its cloud environment
If your project builds and runs without any private dependencies, you do not need a Self-hosted Daemon. provides a cloud build environment that handles standard, publicly accessible setups.

How It Works

The Modelcode Daemon is a lightweight binary (mcode) that runs on a machine within your network. Once started, it:
  1. Registers with and begins sending periodic heartbeats
  2. Polls for pending jobs (build, test, validation tasks)
  3. Executes commands on the host machine’s shell
  4. Reports results and logs back to

Command Execution Model

The daemon executes each command in a new shell process on the host machine. There is no persistent shell session between commands — each step (install, build, run, test) starts a fresh shell -c "command" invocation. All lifecycle commands are executed in a POSIX shell environment. Windows CMD or PowerShell syntax is not supported.
The Modelcode Daemon executes lifecycle commands in a POSIX-compliant shell environment. Linux and macOS are fully supported.
What this means in practice:
  • Environment variables Use the Modelcode UI setup to configure environment variables and not via the Lifecycle commands.
  • Working directory is managed by the daemon and stays consistent across all commands within a single job. You do not need to cd into the project directory, unless commands should be executed in a nested directory in the project.
  • Concatenated Commands In the case multiple commands should be executed in the same step, use ’&&’ to concat commands that share the same shell context.
  • Private repositories The daemon executes lifecycle commands exactly as defined. If Composer is configured to require authentication for private repositories, those credentials must be present on the daemon host or supplied via encrypted environment variables.
The daemon runs commands with the same permissions as the user that started the mcode process. Make sure the user has access to the tools and services your project needs (e.g., language runtimes, network access to private registries).

Setting Up the Daemon

Prerequisites

  • A machine on your network that can reach your private services
  • A Modelcode account with an active project
  • Network connectivity from the machine to *.modelcode.ai
  • All dependencies of the migration project should be available to the Daemon
  • POSIX-compliant operating system (Linux or macOS)
The Modelcode Daemon currently supports POSIX environments only.

Language-Specific Requirements (PHP)

If your project uses PHP and Composer:
  • PHP must be installed on the daemon host
  • Composer must be installed and available in PATH
  • Any required PHP extensions must be installed
Verify PHP and Composer are available:
php -v
composer -v

Supported Operating Systems

  • Linux (x86_64, ARM64)
  • macOS (Intel & Apple Silicon)
Windows native execution is not supported at this time.
To set up the daemon, open your project in Modelcode and navigate to the Build Environment section. Select Self Hosted as your environment type. The UI walks you through each step with platform-specific commands and input fields. At a high level, the onboarding flow covers:
  1. Generate an API key — Creates credentials for the daemon to authenticate with
  2. Install the daemon — Download and install the mcode binary on your target machine
  3. Set up encryption — Generate a key pair so the daemon can securely handle secrets
  4. Start the daemon — Run the daemon process and connect it to
  5. Verify the connection — Confirm the daemon is registered and online
  6. Configure lifecycle commands — Define the install, build, run, health check, and test commands for your project
  7. Configure environment variables — Add any variables your application needs at build or runtime, with optional secret encryption
  8. Validate the setup — Run an end-to-end validation that executes each lifecycle command in sequence
For production use, run mcode install-service followed by mcode start to run as a background service (e.g., using systemd, launchd, or a process manager like pm2). This ensures the daemon restarts automatically after reboots.

Environment Variables and Registry Access

Private Registry Access (Artifactory)

If your dependencies are hosted in a private Artifactory instance:
  • The daemon host must have network access to Artifactory
  • Composer must be configured to authenticate against Artifactory
  • Required credentials (tokens, username/password, or auth.json) must be available at runtime
Authentication options include:
  • Composer auth.json
  • Environment variables
If credentials are configured via environment variables, they should be stored as encrypted variables in the Morph UI.

Troubleshooting

Daemon Shows as Offline

The daemon appears offline when has not received a heartbeat within the last 60 seconds. Check if the daemon process is running:
ps aux | grep mcode
If the process is not running, start it again with mcode run/start. Check network connectivity: The daemon must be able to reach Morph server over HTTPS. Verify with:
curl -I https://<SERVER_URL>
If this fails, check your firewall rules, proxy settings, or VPN configuration. Check the daemon logs: Run mcode logs to show the last log lines. Alternatively the logs are written to the logs/ directory next to the mcode binary. Look for connection errors or authentication failures. Common causes:
  • The mcode run process was killed or the machine rebooted without a service manager configured
  • A network change (VPN disconnect, firewall rule update) is blocking outbound HTTPS traffic

Command Not Found

The daemon inherits the PATH from the shell that started it. When installed as a system service, it takes a snapshot of the current PATH and stores it in its config file. If you install new tools after the daemon is already running as a service, update the stored path with mcode refresh-path and restart the daemon.

Test Generation Failed

Test generation failures occur when cannot generate tests for your project. This typically relates to the build or run steps. Application failed to build: Check the install and build command output in the validation logs. Common causes:
  • Missing dependencies that are only available on your private network
  • Incorrect build command — verify it works when run manually on the same machine
  • Environment variables missing — add them in the Modelcode UI
Application failed to start: If the build succeeds but the run command fails:
  • Check that the port your application listens on is not already in use
  • Verify that required services (databases, APIs) are reachable from the host machine
  • Review the run command output for startup errors
Health check timed out: If the application starts but the health check never succeeds:
  • Confirm the health check URL and port match your application’s configuration
  • Check that the application is binding to 0.0.0.0 or localhost, not a specific interface
  • Increase the health check timeout if your application has a long startup sequence

Functional Testing Failed

Functional test failures mean the test suite ran but one or more tests did not pass. Review the test output: The validation logs show the full test command output, including individual test failures. Read the error messages to determine whether the failure is:
  • A test that depends on external state (e.g., seeded database records, specific API responses)
  • A test environment issue (missing env var, wrong service URL)
  • An actual bug surfaced by the generated tests
Tests depend on unavailable services: If tests require services that are not running on the daemon host:
  • Start those services before running mcode run
  • Add their connection details as environment variables in the Modelcode UI
Tests time out:
  • Check the command_timeout configuration (default is 10 minutes)
  • If your test suite takes longer, consider splitting it or increasing the timeout

API Key Issues

“Unauthorized” or “Authentication failed”:
  • Verify the API key in your daemon configuration matches the one shown in the Modelcode UI

Encryption Key Mismatch

Secrets fail to decrypt: If the daemon cannot decrypt secret environment variables:
  • Re-run mcode encryption generate and update the public key in the Modelcode UI
  • Restart the daemon with mcode run
  • Re-save your environment variables in the UI to re-encrypt them with the new key

FAQ

Does the Modelcode Daemon support Windows?

The daemon supports POSIX-compliant environments (Linux/macOS).

Next Steps