logo

Contributing Your VM Image to Swiftor

This guide outlines how to prepare and configure your custom Virtual Machine (VM) images for integration into the Swiftor platform. Our system relies on a structured configuration to ensure seamless deployment and management.

Core Concepts

Swiftor Variables

When configuring your image, certain placeholder variables will be dynamically resolved by Swiftor at runtime:

  • ${SWIFTOR_USERNAME}: The username of the Swiftor user.
  • ${SWIFTOR_PASSWORD}: The user's password (handle with care, primarily for initial setup).
  • ${SWIFTOR_VMID}: The unique identifier for the VM instance, can be used for configuring CORS origin (e.g., https://${SWIFTOR_VMID}.swiftor.io).

Deployment Model

Swiftor deploys VM images as a single container and single service using Docker Swarm. Your image configuration should be tailored for this model.

Image Configuration Schema (ImageConfig)

The primary configuration for your VM is defined by the ImageConfig schema. Below is a breakdown of its fields:

FieldTypeDescriptionDefault Value
image_prefixstrThe prefix for the Docker image name. Defaults to "registry.swiftor.io/linuxserver/". Use an empty string "" for images from Docker Hub, or specify other registry prefixes (e.g., ghcr.io/) if needed."registry.swiftor.io/linuxserver/"
image_namestrRequired. The name of the Docker image (e.g., "code-server", "webtop").N/A
image_tagOptional[str]The tag for the Docker image (e.g., "latest", "version-1.2.3"). For webtop images, this is often constructed from distribution and desktop.None (often implies "latest")
is_webtopboolSet to True if the image is a base webtop image (e.g., Ubuntu, Debian, Fedora based webtops).False
security_profileSecurityProfileDefines the security context for the container.SecurityProfile.NONE
default_envDict[str, str]Default environment variables for the container. Swiftor variables can be used.{} (empty dict)
additional_envDict[str, str]Additional environment variables.{} (empty dict)
default_config_pathstrContainer path for the main application config. This is bound to a dedicated storage area for the VM instance within the user's storage space."/config"
volumesDict[str, VolumeBinding]Additional custom volume bindings. See VolumeBinding Configuration.{} (empty dict)
networkingNetworkingConfigNetworking configuration. See NetworkingConfig Configuration.Default NetworkingConfig()
traefikTraefikConfigTraefik reverse proxy configuration. See TraefikConfig Configuration.Default TraefikConfig()

Generating Full Image Name

The full Docker image name used by the system is constructed as follows:

  • If is_webtop is True, and distribution and desktop parameters are provided during deployment: {image_prefix}{image_name}:{distribution}-{desktop}
  • Else if image_tag is specified: {image_prefix}{image_name}:{image_tag}
  • Otherwise (tag is None or empty): {image_prefix}{image_name} (Docker typically defaults to latest if no tag is provided to docker pull)

SecurityProfile Options

ValueDescription
NONENo specific security profiles beyond Docker defaults.
BASICUnconfined seccomp.
ADVANCEDUnconfined seccomp + AppArmor.
FULLIncludes NET_ADMIN capabilities and device access.

VolumeBinding Configuration

Defines how host directories are mapped to container paths for additional volumes.

FieldTypeDescriptionDefault Value
host_pathstrPath on the host. If relative (no leading /), it's mapped to a subdirectory within the user's general storage area (e.g., a host_path of "data/myapp" maps to a data/myapp folder in the user's shared storage). If absolute, it's used as is (special cases only).N/A
container_pathstrAbsolute path inside the container where the host_path will be mounted.N/A
requiredboolIf True, the system attempts to ensure the host directory exists. Set to False for pre-existing system paths.True

Key Volume Binding Points:

  1. Default Config: The ImageConfig.default_config_path (e.g., /config in container) is always bound to a dedicated directory for that specific VM under the user's storage (conceptually storage/vms/YOUR_VM_ID/).
  2. Additional Volumes: Defined in ImageConfig.volumes.
    • If VolumeBinding.host_path is relative (e.g., "mydata", "app/cache"), it's resolved to a path like storage/mydata or storage/app/cache directly under the user's main storage area.
    • This means additional volumes are typically placed in subdirectories within the user's general storage area, like storage/data/, storage/logs/, based on the host_path provided.

NetworkingConfig Configuration

Manages the primary network exposure of your application.

FieldTypeDescriptionDefault Value
entrypoint_portintPrimary port inside the container your application listens on. This is exposed as the main HTTP/HTTPS endpoint.3000
additional_routesDict[str, int]Defines additional HTTP routes managed by Traefik. Key is URL pathname (e.g., "api"), value is the container port. Example: {"manage": 8081}{}

TraefikConfig Configuration

Controls settings for the Traefik reverse proxy.

FieldTypeDescriptionDefault Value
enableboolEnable Traefik routing for this image.True
custom_labelsList[str]Raw Docker labels for Traefik (advanced usage).[]
additional_networkingboolIf True, allows user-defined subdomains or more complex port forwarding (platform-dependent capability).False

Enhanced Example: code-server

Let's look at the code-server configuration to illustrate these concepts:

python
# Example ImageConfig code block for submission
"code-server": ImageConfig(
    # Image Identification
    image_prefix="registry.swiftor.io/linuxserver/", # Default Swiftor registry
    image_name="code-server",
    image_tag="latest",

    # Security (defaulting to NONE, but can be specified)
    # security_profile=SecurityProfile.BASIC, 

    # Environment Variables
    default_env={
        "SUDO_PASSWORD": "${SWIFTOR_PASSWORD}",      # Use Swiftor-resolved password
        "DEFAULT_WORKSPACE": "/config/workspace"     # code-server will use this path inside the container
                                                     # This /config/workspace will be under the VM's specific storage area
                                                     # (conceptually: storage/vms/${SWIFTOR_VMID}/workspace)
    },
    
    # Volume Configuration
    # default_config_path is "/config" by default.
    # So, /config in container maps to the VM's dedicated storage area (conceptually: storage/vms/${SWIFTOR_VMID}/).
    
    volumes={
        "workspace_data": VolumeBinding(  # Descriptive name for this binding
            host_path="code-server_projects", # Relative to user's general storage area.
                                             # Resolves to a folder like: storage/code-server_projects
            container_path="/projects"       # Mount this shared project folder to /projects in container
        ),
        "another_config": VolumeBinding(
             host_path="my_global_configs/coder_settings", # Resolves to a path like: storage/my_global_configs/coder_settings
             container_path="/etc/global_coder_settings"   # Example of another shared config
        )
    },

    # Networking
    networking=NetworkingConfig(
        entrypoint_port=8443 # Main port for code-server web UI
        # additional_routes={"api": 8444} # If code-server had a separate API port on /api path
    ),
)

Explanation of the code-server example:

  1. Image Source: It pulls registry.swiftor.io/linuxserver/code-server:latest.
  2. Environment:
    • SUDO_PASSWORD is set using the user's Swiftor password.
    • DEFAULT_WORKSPACE is set to /config/workspace. Since /config (the default_config_path) inside the container is mapped to the VM-specific storage area, code-server's default projects will be stored in that VM's dedicated space (e.g., storage/vms/${SWIFTOR_VMID}/workspace).
  3. Volumes:
    • The primary configuration for code-server (if it writes to /config) goes into the VM's dedicated storage area.
    • workspace_data: A directory named code-server_projects from the user's general storage area (conceptually storage/code-server_projects) is mounted into the container at /projects. This allows users to have a persistent project directory.
    • another_config: Illustrates mounting another shared configuration from the user's general storage area.
  4. Networking: The code-server UI will be accessible on port 8443 through the VM's main URL.

The host_path in VolumeBinding: If it's an empty string "" or a simple name like "my_data", it's relative to the user's main storage area (conceptually storage/). So, a host_path: "data/coder" would map to a data/coder folder within the user's general storage space.The dedicated named data volume separate from the main VM config directory (which is conceptually storage/vms/${SWIFTOR_VMID}/) is bound to a path like storage/data/ (or any other path specified in host_path relative to the user's general storage area).

Preparing and Publishing

  1. Docker Image: Ensure your Docker image is built and pushed to an accessible registry. If using a custom image_prefix for a non-standard registry, ensure its accessibility. For images intended for registry.swiftor.io/linuxserver/ or other Swiftor-managed prefixes, please coordinate with the Swiftor team regarding the image push.
  2. Configuration: Prepare an ImageConfig code block (like the example above) defining your image and its settings.
  3. Testing: Test your image and configuration thoroughly in a development environment that mimics Swiftor's deployment if possible.
  4. Submission: Submit your ImageConfig code block to our Discord Channel for review and integration.

Ensure that your image adheres to the single container, single service model and that all necessary ports, volumes, and environment variables are correctly specified. Using the Swiftor variables (${SWIFTOR_USERNAME}, ${SWIFTOR_PASSWORD}, ${SWIFTOR_VMID}) where appropriate will help ensure your image integrates smoothly.