Vix.cpp v2.7.0 is here Read the blog
Skip to content

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.

json
{
  "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

FieldPurpose
nameThe systemd service name used by Vix commands.
userThe Linux user that should run the application process.
working_dirThe directory where the process starts. This matters for .env, static files, templates, storage, and relative paths.
execThe executable path used to start the application.
restartThe restart policy for the service.
restart_secDelay before systemd restarts the process.
limit_nofileFile 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.

bash
vix service status
vix service restart

When the service unit needs to be generated or installed, use:

bash
vix service install

The 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.

bash
sudo systemctl daemon-reload

How 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.

bash
vix deploy

vix production status uses the service status as one of the first checks before health, proxy, and log diagnostics.

bash
vix production status

vix health can verify that the configured service is running before checking the local or public health endpoint.

bash
vix health

vix logs uses the service name to read application logs from systemd.

bash
vix logs app
vix logs errors

This 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.

json
{
  "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.

json
{
  "production": {
    "env": {
      "required": [
        "APP_NAME",
        "APP_ENV",
        "SERVER_PORT",
        "DATABASE_ENGINE",
        "DATABASE_SQLITE_PATH"
      ]
    }
  }
}

Then run:

bash
vix env check --production

This 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.

json
{
  "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.

json
{
  "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.

json
{
  "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.

bash
vix service status

Then verify that the production workflow can read the same service information.

bash
vix deploy --dry-run
vix production status

If the service is installed and the binary exists, restart it and check health.

bash
vix service restart
vix health local

A 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.

Released under the MIT License.