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.
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
).Swiftor deploys VM images as a single container and single service using Docker Swarm. Your image configuration should be tailored for this model.
ImageConfig
) The primary configuration for your VM is defined by the ImageConfig
schema. Below is a breakdown of its fields:
Field | Type | Description | Default Value |
---|---|---|---|
image_prefix | str | The 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_name | str | Required. The name of the Docker image (e.g., "code-server", "webtop"). | N/A |
image_tag | Optional[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_webtop | bool | Set to True if the image is a base webtop image (e.g., Ubuntu, Debian, Fedora based webtops). | False |
security_profile | SecurityProfile | Defines the security context for the container. | SecurityProfile.NONE |
default_env | Dict[str, str] | Default environment variables for the container. Swiftor variables can be used. | {} (empty dict) |
additional_env | Dict[str, str] | Additional environment variables. | {} (empty dict) |
default_config_path | str | Container 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" |
volumes | Dict[str, VolumeBinding] | Additional custom volume bindings. See VolumeBinding Configuration. | {} (empty dict) |
networking | NetworkingConfig | Networking configuration. See NetworkingConfig Configuration. | Default NetworkingConfig() |
traefik | TraefikConfig | Traefik reverse proxy configuration. See TraefikConfig Configuration. | Default TraefikConfig() |
The full Docker image name used by the system is constructed as follows:
is_webtop
is True
, and distribution
and desktop
parameters are provided during deployment: {image_prefix}{image_name}:{distribution}-{desktop}
image_tag
is specified: {image_prefix}{image_name}:{image_tag}
None
or empty): {image_prefix}{image_name}
(Docker typically defaults to latest
if no tag is provided to docker pull
)SecurityProfile
Options Value | Description |
---|---|
NONE | No specific security profiles beyond Docker defaults. |
BASIC | Unconfined seccomp. |
ADVANCED | Unconfined seccomp + AppArmor. |
FULL | Includes NET_ADMIN capabilities and device access. |
VolumeBinding
Configuration Defines how host directories are mapped to container paths for additional volumes.
Field | Type | Description | Default Value |
---|---|---|---|
host_path | str | Path 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_path | str | Absolute path inside the container where the host_path will be mounted. | N/A |
required | bool | If True , the system attempts to ensure the host directory exists. Set to False for pre-existing system paths. | True |
Key Volume Binding Points:
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/
).ImageConfig.volumes
. 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.storage/data/
, storage/logs/
, based on the host_path
provided.NetworkingConfig
Configuration Manages the primary network exposure of your application.
Field | Type | Description | Default Value |
---|---|---|---|
entrypoint_port | int | Primary port inside the container your application listens on. This is exposed as the main HTTP/HTTPS endpoint. | 3000 |
additional_routes | Dict[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.
Field | Type | Description | Default Value |
---|---|---|---|
enable | bool | Enable Traefik routing for this image. | True |
custom_labels | List[str] | Raw Docker labels for Traefik (advanced usage). | [] |
additional_networking | bool | If True , allows user-defined subdomains or more complex port forwarding (platform-dependent capability). | False |
code-server
Let's look at the code-server
configuration to illustrate these concepts:
# 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:
registry.swiftor.io/linuxserver/code-server:latest
.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
).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.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).
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.ImageConfig
code block (like the example above) defining your image and its settings.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.