OPS Documentation

repository·master·Indexed 23 days ago

https://github.com/nanovms/ops

OPS is a tool for packaging, creating, and running applications as Nanos unikernels, enabling minimal overhead and simplified deployment to cloud providers like AWS, Azure, GCP, IBM, Oracle Cloud, Digital Ocean, Linode, Vultr, and UpCloud. It provides commands for building bootable images from ELF files, orchestrating multiple unikernels via 'compose', managing scheduled tasks with 'cron', and handling cross-build environments and image manipulation.

Tokens
11.7K
Snippets
15
Records
95
Agent score
79%

What's inside OPS

  1. What is a Unikernel?

    master

    A unikernel is a single-process system designed to run exactly one application. Unlike general-purpose operating systems (like Linux) that support multiple users and programs, a unikernel is optimized for performance, security, and minimal size by stripping away unnecessary abstractions.

    Key characteristics include:

    • Single Process: The system runs one application, though it supports multiple threads. For interpreted languages (e.g., Ruby, Python), concurrency is achieved by running multiple unikernel VMs behind a load balancer rather than running multiple processes within a single OS.
    • No Shell or Users: There is no remote shell to log into and no concept of multiple users. While OPS may include a stubbed/fake user to satisfy libc requirements, standard Unix permissions have no practical meaning because only one program is running.
  2. What is an OPS Package?

    master
    An OPS package is a method for distributing an application along with its required dependencies as a bundled resource. This allows users to distribute software without requiring them to manually compile code or resolve missing dependencies. Packages can be OS-related or application-specific. They are intended for general software distribution (similar to apt-get) rather than internal developer-specific tools.
  3. Running OPS on Apple M1/M2 (ARM)

    master

    OPS provides full support for running native ARM applications (ELFs) on Apple M1 and M2 chips with hardware acceleration (no Rosetta required).

    Important: If you intend to deploy the same application to x86-based servers, you must explicitly re-build your images for x86, as the default build target on M1/M2 is arm64.

  4. Deploy to the Cloud

    master

    OPS simplifies cloud deployment by pushing orchestration to the provider. Supported providers include:

    • Major Clouds: Azure, AWS, Google Cloud, IBM, Oracle Cloud (OCI).
    • Other Providers: Digital Ocean, Linode, Vultr, UpCloud.

    You can browse available pre-made packages via the shell:

    ops pkg list

    Or visit the public repository at https://repo.ops.city/.

    ops pkg list
  5. Create an OPS package from Docker

    master

    You can automatically generate an OPS package directly from a Docker image using the ops pkg from-docker command. You must specify the Docker image and the flag -f followed by the name of the executable within that image.

    ops pkg from-docker node:16.3.0 -f node
  6. Install OPS

    master

    You can install OPS using several methods depending on your operating system:

    Use the following shell script to install the binary directly:

    curl https://ops.city/get.sh -sSfL | sh

    MacOS via Homebrew

    Tap the repository and install the package:

    brew tap nanovms/homebrew-ops
    brew install nanovms/ops/ops

    Debian / Redhat

    Add the Fury APT source and install:

    sudo vi /etc/apt/sources.list.d/fury.list
    # Add the following line to the file:
    # deb [trusted=yes] https://apt.fury.io/nanovms/ /
    
    sudo apt-get update && sudo apt-get install ops

    Build from Source

    Requires Go version 1.25.x or greater.

    make deps
    make build

    For macOS builds, use:

    GO111MODULE=on go build -ldflags "-w"
    curl https://ops.city/get.sh -sSfL | sh
  7. Create an OPS package manually

    master

    To create a package manually, follow these steps to structure the directory, populate dependencies, and create a manifest:

    1. Create the directory

    Create a directory following the naming convention [PKGNAME]_[PKGVERSION].

    2. Populate the directory

    The directory must contain:

    • The application binary.
    • A package.manifest file.
    • A sysroot directory containing all necessary shared libraries (e.g., libc.so.6, libm.so.6) and system files (e.g., /etc/ssl/certs).

    To identify required libraries, you can use the ldd command on your binary. Ensure you also include essential libraries like libnss and libresolv.

    3. Create the package.manifest

    The manifest is a JSON file that defines the entry point and version. Example for a Lua package:

    {
       "Program":"lua_5.2.4/lua",
       "Args" : ["lua"],
       "Version":"5.2.4"
    }

    4. Tar the package

    Compress the directory into a .tar.gz file using the format [PKGNAME]_[PKGVERSION].tar.gz.

    tar czf "$PKGNAME"_"$PKGVERSION".tar.gz "$PKGNAME"_"$PKGVERSION"
  8. Manage NanoVMs networks

    master

    The network command is used to manage NanoVMs networks. Note that this command is currently for Linux only and relies on bridgetools and dnsmasq. On macOS, networking uses vmnet-bridged instead.

    Available subcommands:

    • create: Creates a new bridged network.
    • list: Lists all existing networks.
    • delete <network_name>: Deletes a specific network.
  9. Use the ops CLI

    master

    The ops command is the entrypoint for managing NanoVMs operations. It provides a hierarchical command structure for managing builds, environments, images, instances, networks, and more.

    Global configuration can be managed via a --config flag, which allows you to specify a configuration file path. The CLI also supports global flags that can be merged into the configuration during execution.

  10. How package resolution and merging works

    master

    OPS uses a specific hierarchy to resolve and apply package configurations to your local configuration:

    1. Architecture Detection: OPS determines your architecture (e.g., amd64 or arm64) to locate the correct package files.
    2. Path Resolution:
      • If --local is used, it looks in $OPS_HOME/local_packages/<arch>/<package>.
      • Otherwise, it looks in $OPS_HOME/packages/<arch>/<slugged_package>.
      • It supports a "fuzzy" versioning fallback where it checks for a v prefix on the version (e.g., pkg_v1.0.0).
    3. Configuration Merging: When a package is loaded, its package.manifest is parsed, and its settings are merged into your existing configuration. This includes:
      • Program, Version, Language, and Description.
      • Args, Dirs, and Files (these are appended to your existing lists).
      • MapDirs and Env (these are merged into your existing maps).
      • BaseVolumeSz, NameServers, and TargetRoot (these are applied if not already set).
      • Image Names: If no image name is provided, OPS derives an image name from the package's program name and stores it in the RunConfig and CloudConfig.
  11. Configure OPS using JSON files and environment interpolation

    master

    OPS accepts plain JSON configuration files to define application arguments and directories.

    Config File Format

    {
      "Args":["one","two"],
      "Dirs":["myapp/static"]
    }

    Environment Variable Interpolation

    You can use Golang-style string interpolation (e.g., ${USER} or $PASSWORD) within your JSON config files. To enable this feature, you must set the ops_render_config environment variable to true.

    Example usage:

    ops_render_config=true ops run -p <port> -c <file> <app>

    Example config with interpolation:

    {
      "Args":[
        "--user",
        "${USER}",
        "--password",
        "$PASSWORD"
      ],
      "Dirs":["myapp/static"]
    }