Production Service
The production service section describes the process that runs your application on a Linux server. It gives Vix a stable name for the service, the user that should run it, the working directory, the executable to start, and a few runtime policies such as restart behavior and file descriptor limits.
This page is about the operational process, not the application source layout. A project generated by vix new --template backend already includes a service section in vix.json, but the same configuration can be added to an existing C++ project, a custom CMake project, or a Vix project that does not use the generated backend or web templates.
Why the service section matters
A production application needs a process manager. On most Linux servers, that role is handled by systemd. The application binary may be simple, but the way it is started still matters: it needs a working directory, an environment, restart rules, permissions, and a service name that other tools can use.
Vix reads this information from vix.json so the rest of the production workflow can speak about the same service. Deployment can restart it, health checks can verify it, logs can read from it, and environment checks can compare the project configuration with the service runtime environment. Without this shared service metadata, every command would need to guess which process belongs to the project.
Basic configuration
The service configuration lives under production.service.
{
"name": "myapp",
"production": {
"service": {
"name": "myapp",
"user": "deploy",
"working_dir": "/srv/myapp",
"exec": "/srv/myapp/bin/myapp",
"restart": "always",
"restart_sec": 3,
"limit_nofile": 65535
}
}
}The values should describe the deployed application as it really runs on the server. Use the final service name, the final working directory, and the executable path that will exist after the build step has completed.
Fields
| Field | Purpose |
|---|---|
name | The systemd service name used by Vix commands. |
user | The Linux user that should run the application process. |
working_dir | The directory where the process starts. This matters for .env, static files, templates, storage, and relative paths. |
exec | The executable path used to start the application. |
restart | The restart policy for the service. |
restart_sec | Delay before systemd restarts the process. |
limit_nofile | File descriptor limit for the process. |
The most important fields are name, working_dir, and exec. If those are wrong, Vix may be able to build the project, but production commands will not be able to restart or inspect the running application correctly.
Commands
Once the service metadata is present, the service command can be used to inspect and control the process.
vix service status
vix service restartWhen the service unit needs to be generated or installed, use:
vix service installThe exact service file is derived from the production metadata in vix.json. After installing or changing a systemd unit, the server may require a daemon reload before the service can be started or restarted correctly.
sudo systemctl daemon-reloadHow service metadata is used by other commands
The service section is not isolated. It becomes part of the wider production workflow.
vix deploy uses the service name when it restarts the application after a successful build.
vix deployvix production status uses the service status as one of the first checks before health, proxy, and log diagnostics.
vix production statusvix health can verify that the configured service is running before checking the local or public health endpoint.
vix healthvix logs uses the service name to read application logs from systemd.
vix logs app
vix logs errorsThis is why the service name should stay consistent across production.service, production.deploy, production.health, and production.logs.
Service and deployment
A typical deployment section references the same service name.
{
"production": {
"service": {
"name": "myapp",
"user": "deploy",
"working_dir": "/srv/myapp",
"exec": "/srv/myapp/bin/myapp"
},
"deploy": {
"pull": true,
"branch": "main",
"build": "vix build --preset release",
"tests": false,
"service": "myapp",
"health_local": true,
"proxy_check": true,
"logs_on_failure": true
}
}
}In this workflow, Vix pulls the configured branch, builds the application, restarts the service, checks that the service is active, and then runs the configured health and proxy checks. If the service name does not match the installed systemd unit, the deployment will fail at the restart or status step.
Service and environment
The service process usually reads runtime values from .env or from systemd environment variables. Vix can compare the project environment files with the production requirements declared in vix.json.
{
"production": {
"env": {
"required": [
"APP_NAME",
"APP_ENV",
"SERVER_PORT",
"DATABASE_ENGINE",
"DATABASE_SQLITE_PATH"
]
}
}
}Then run:
vix env check --productionThis check helps catch missing variables before the application is restarted. It is especially useful when a binary builds correctly but fails at startup because the service environment is incomplete.
Using a relative executable path
Generated Vix templates often use an executable path relative to the project directory.
{
"production": {
"service": {
"name": "myapp",
"user": "deploy",
"working_dir": ".",
"exec": "bin/myapp"
}
}
}This is convenient when the application is deployed from the project root and the working directory is stable. For a server deployment under /srv/myapp, an absolute path is often clearer.
{
"production": {
"service": {
"name": "myapp",
"user": "deploy",
"working_dir": "/srv/myapp",
"exec": "/srv/myapp/bin/myapp"
}
}
}Both styles can work. The important point is that the exec path must be valid from the service environment, and the working directory must be the directory the application expects at runtime.
Using service files in an existing C++ project
An existing CMake project can use the service workflow without adopting the Vix template layout. The build command can remain a normal CMake command, while Vix manages the production metadata around it.
{
"name": "legacy-api",
"production": {
"service": {
"name": "legacy-api",
"user": "deploy",
"working_dir": "/srv/legacy-api",
"exec": "/srv/legacy-api/build/legacy-api",
"restart": "always",
"restart_sec": 3,
"limit_nofile": 65535
},
"deploy": {
"pull": true,
"branch": "main",
"build": "cmake --build build --config Release",
"tests": true,
"test_command": "ctest --test-dir build --output-on-failure",
"service": "legacy-api",
"health_local": true,
"logs_on_failure": true
},
"health": {
"service": "legacy-api",
"local": "http://127.0.0.1:8080/health"
},
"logs": {
"service": "legacy-api",
"nginx_access": "/var/log/nginx/legacy-api.access.log",
"nginx_error": "/var/log/nginx/legacy-api.error.log",
"lines": 120
}
}
}Here, Vix is not replacing CMake. It is using project metadata to run production operations around the existing build system.
Practical workflow
Start by defining the service metadata and checking the service state.
vix service statusThen verify that the production workflow can read the same service information.
vix deploy --dry-run
vix production statusIf the service is installed and the binary exists, restart it and check health.
vix service restart
vix health localA good service configuration should be boring and exact. The service name should match the systemd unit, the executable path should point to the real binary, and the working directory should match the directory where the application expects its files.
Next step
Continue with the health documentation to define the local, public, and WebSocket endpoints that Vix should check after the service starts.