Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
63cb89b
feat(config): add Proxmox LXC provider configuration
mzyy94 Mar 29, 2026
dffc5f3
feat(provider): add Proxmox LXC provider implementation
mzyy94 Mar 29, 2026
621e9b6
test(provider): add Proxmox LXC provider unit tests
mzyy94 Mar 29, 2026
3315ea4
feat(provider): register Proxmox LXC provider
mzyy94 Mar 29, 2026
337de45
test(sabliercmd): update testdata for ProxmoxLXC config fields
mzyy94 Mar 29, 2026
27ad88f
docs(provider): add Proxmox LXC provider documentation
mzyy94 Mar 29, 2026
89e2469
docs(provider): add Proxmox LXC to sidebar with icon
mzyy94 Mar 30, 2026
6bf7473
feat(provider): support node/vmid format for Proxmox LXC instance names
mzyy94 Mar 30, 2026
ee5aa83
fix(provider): check network interfaces for Proxmox LXC readiness
mzyy94 Mar 30, 2026
626c84a
fix(provider): report unrecoverable state on Proxmox LXC start failure
mzyy94 Mar 30, 2026
f3d739d
refactor(provider): use UPID-based async task tracking for Proxmox LX…
mzyy94 Apr 1, 2026
c3e3d84
test(provider): add integration tests for Proxmox LXC provider
mzyy94 Apr 1, 2026
a9d0b94
test(provider): use external test package for Proxmox LXC tests
mzyy94 Apr 1, 2026
9953bad
docs: add Proxmox LXC to provider lists and documentation
mzyy94 Apr 3, 2026
c9ea7a6
fix(provider): allow Proxmox LXC to resolve containers without sablie…
mzyy94 Apr 7, 2026
ddf4070
chore: got mod tidy
mzyy94 Apr 16, 2026
6e482fc
docs(proxmox-lxc): fix failed-start TTL description to match implemen…
mzyy94 Apr 16, 2026
607c83f
fix(proxmox-lxc): use write lock for pendingTasks to prevent data rac…
mzyy94 Apr 16, 2026
323887a
Merge branch 'main' into proxmox-lxc-provider
mzyy94 Apr 16, 2026
b3a5364
Merge branch 'main' into proxmox-lxc-provider
mzyy94 May 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Whether you don't want to overload your Raspberry Pi, or your QA environment is
- [Docker Swarm](#docker-swarm)
- [Podman](#podman)
- [Kubernetes](#kubernetes)
- [Proxmox LXC](#proxmox-lxc)
- [Usage with Reverse Proxies](#usage-with-reverse-proxies)
- [Apache APISIX](#apache-apisix)
- [Caddy](#caddy)
Expand Down Expand Up @@ -247,8 +248,8 @@ sablier --configFile=path/to/myconfigfile.yml

```yaml
provider:
# Provider to use to manage containers (docker, swarm, kubernetes)
name: docker
# Provider to use to manage containers (docker, swarm, kubernetes, podman, proxmox_lxc)
name: docker
server:
# The server port to use
port: 10000
Expand Down Expand Up @@ -390,6 +391,21 @@ Sablier provides native Kubernetes support for managing deployments, scaling wor

📚 **[Full Documentation](https://sablierapp.dev/#/providers/kubernetes)**

---

### Proxmox LXC

<img src="./docs/assets/img/proxmox.png" alt="Proxmox" width="100" align="right" />

Sablier supports Proxmox VE for managing LXC containers on demand via the Proxmox API.

**Features:**
- Connects to the Proxmox VE API with token authentication
- Starts/Stops LXC containers
- Discovers containers by `sablier` tag

📚 **[Full Documentation](https://sablierapp.dev/#/providers/proxmox_lxc)**

## Usage with Reverse Proxies

Sablier is an API server that manages workload lifecycle. To automatically wake up workloads when users access your services, you can integrate Sablier with reverse proxy plugins.
Expand Down
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ This allows you to start your containers on demand and shut them down automatica
Throughout this documentation, we use these terms to remain provider-agnostic:

- **Session**: A session is a set of **instances**
- **Instance**: An instance is either a Docker container, Docker Swarm service, Kubernetes deployment, or Kubernetes StatefulSet
- **Instance**: An instance is either a Docker container, Docker Swarm service, Kubernetes deployment, Kubernetes StatefulSet, or Proxmox LXC container

## Credits

Expand Down
1 change: 1 addition & 0 deletions docs/_sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- [<img src="assets/img/docker_swarm.png" height=24px width=24px />Docker Swarm](/providers/docker_swarm)
- [<img src="assets/img/kubernetes.png" height=24px width=24px />Kubernetes](/providers/kubernetes)
- [<img src="assets/img/podman.png" height=24px width=24px />Podman](/providers/podman)
- [<img src="assets/img/proxmox.png" height=24px width=24px />Proxmox LXC](/providers/proxmox_lxc)
- **Reverse Proxy Plugins**
- [Overview](/plugins/overview)
- [<img src="assets/img/apacheapisix.png" height=24px width=24px />Apache APISIX](/plugins/apacheapisix)
Expand Down
Binary file added docs/assets/img/proxmox.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ sablier --configFile=path/to/myconfigfile.yml

```yaml
provider:
# Provider to use to manage containers (docker, swarm, kubernetes)
# Provider to use to manage containers (docker, swarm, kubernetes, podman, proxmox_lxc)
name: docker
docker:
# Strategy to use for stopping Docker containers: stop or pause (default: stop)
Expand Down Expand Up @@ -117,7 +117,7 @@ sablier start --strategy.dynamic.custom-themes-path /my/path
```
-h, --help help for start
--provider.docker.strategy string Strategy to use to stop docker containers (stop or pause) (default "stop")
--provider.name string Provider to use to manage containers [docker swarm kubernetes] (default "docker")
--provider.name string Provider to use to manage containers [docker swarm kubernetes podman proxmox_lxc] (default "docker")
--server.base-path string The base path for the API (default "/")
--server.port int The server port to use (default 10000)
--sessions.default-duration duration The default session duration (default 5m0s)
Expand Down
1 change: 1 addition & 0 deletions docs/providers/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ A Provider typically has the following capabilities:
| [Docker Swarm](docker_swarm) | `docker_swarm` or `swarm` | Scale down to zero and up **services** on demand |
| [Kubernetes](kubernetes) | `kubernetes` | Scale down and up **deployments** and **statefulsets** on demand |
| [Podman](podman) | `podman` | Stop and start **containers** on demand |
| [Proxmox LXC](proxmox_lxc) | `proxmox_lxc` | Stop and start **LXC containers** on demand via Proxmox VE API |

*Your Provider is not on the list? [Open an issue to request the missing provider here!](https://github.com/sablierapp/sablier/issues/new?assignees=&labels=enhancement%2C+provider&projects=&template=instance-provider-request.md&title=Add+%60%5BPROVIDER%5D%60+provider)*

Expand Down
123 changes: 123 additions & 0 deletions docs/providers/proxmox_lxc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Proxmox LXC

The Proxmox LXC provider communicates with the Proxmox VE API to start and stop LXC containers on demand.

## Use the Proxmox LXC provider

In order to use the Proxmox LXC provider you can configure the [provider.name](../configuration) property.

<!-- tabs:start -->

#### **File (YAML)**

```yaml
provider:
name: proxmox_lxc
proxmox-lxc:
url: "https://proxmox.local:8006/api2/json"
token-id: "root@pam!sablier"
token-secret: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
tls-insecure: false
```

#### **CLI**

```bash
sablier start \
--provider.name=proxmox_lxc \
--provider.proxmox-lxc.url=https://proxmox.local:8006/api2/json \
--provider.proxmox-lxc.token-id=root@pam!sablier \
--provider.proxmox-lxc.token-secret=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
```

#### **Environment Variable**

```bash
SABLIER_PROVIDER_NAME=proxmox_lxc
SABLIER_PROVIDER_PROXMOX_LXC_URL=https://proxmox.local:8006/api2/json
SABLIER_PROVIDER_PROXMOX_LXC_TOKEN_ID=root@pam!sablier
SABLIER_PROVIDER_PROXMOX_LXC_TOKEN_SECRET=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
SABLIER_PROVIDER_PROXMOX_LXC_TLS_INSECURE=false
```

<!-- tabs:end -->

## Configuration

| Property | CLI Flag | Environment Variable | Default | Description |
|---|---|---|---|---|
| `url` | `--provider.proxmox-lxc.url` | `SABLIER_PROVIDER_PROXMOX_LXC_URL` | *(required)* | Proxmox VE API URL |
| `token-id` | `--provider.proxmox-lxc.token-id` | `SABLIER_PROVIDER_PROXMOX_LXC_TOKEN_ID` | *(required)* | API token ID (e.g. `root@pam!sablier`) |
| `token-secret` | `--provider.proxmox-lxc.token-secret` | `SABLIER_PROVIDER_PROXMOX_LXC_TOKEN_SECRET` | *(required)* | API token secret |
| `tls-insecure` | `--provider.proxmox-lxc.tls-insecure` | `SABLIER_PROVIDER_PROXMOX_LXC_TLS_INSECURE` | `false` | Skip TLS certificate verification (for self-signed certs) |

## Create a Proxmox API Token

1. In the Proxmox web UI, go to **Datacenter > Permissions > API Tokens**
2. Click **Add** and create a token for a user (e.g. `root@pam`)
3. Uncheck **Privilege Separation** so the token inherits the user's permissions
4. Note the **Token ID** (e.g. `root@pam!sablier`) and **Secret**

The token needs the following permissions on the LXC containers:
- `VM.PowerMgmt` — to start and stop containers
- `VM.Audit` — to read container status and configuration

## Register containers

For Sablier to work, it needs to know which LXC containers to start and stop.

You have to register your containers by opting-in with **Proxmox tags**.

```yaml
arch: amd64
cores: 2
hostname: whoami
memory: 4096
net0: name=eth0,bridge=vmbr0,hwaddr=BC:24:11:81:7C:C4,ip=dhcp,type=veth
ostype: debian
rootfs: local-lvm:vm-100-disk-0,size=8G
swap: 512
tags: sablier;sablier-group-mygroup
unprivileged: 1
```

### Add tags via the CLI

```bash
pct set 100 -tags "sablier;sablier-group-mygroup"
```

### Add tags via the Web UI

In the Proxmox web UI, select a container and click the **pencil icon** next to the tags in the toolbar (next to the container name) to edit tags.

### Tags reference

| Tag | Description |
|---|---|
| `sablier` | **Required.** Marks the container as managed by Sablier. |
| `sablier-group-<name>` | Optional. Assigns the container to a group. Defaults to `default` if not specified. |

## Instance naming

Sablier uses the LXC container **hostname** as the instance name. You can also reference containers by their **VMID** (e.g. `100`) or by **node/VMID** format (e.g. `pve1/100`).

!> Hostnames must be unique among Sablier-managed containers. If duplicate hostnames are detected, Sablier will return an error.

## Multi-node support

The Proxmox LXC provider automatically discovers all nodes in the cluster and scans for tagged containers across all of them. No additional configuration is required for multi-node setups.

## How does Sablier know when a container is ready?

Sablier checks the LXC container status reported by Proxmox. Additionally, for `running` containers, Sablier verifies that at least one non-loopback network interface has an IP address assigned before reporting the container as ready.

| Proxmox Status | Sablier Status |
|---|---|
| `running` (with IP) | Ready |
| `running` (no IP yet) | Not Ready |
| `stopped` | Not Ready |
| `stopped` (after failed start) | Unrecoverable |
| Other | Unrecoverable |

?> When a start task fails (e.g. `startup for container '100' failed`), Sablier marks the instance as **Unrecoverable** instead of retrying indefinitely. The failed-start state is cleared automatically after a short fixed TTL (currently about 30 seconds), allowing a new start attempt on a subsequent request even if the session is still active.
7 changes: 7 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/gin-gonic/gin v1.12.0
github.com/google/go-cmp v0.7.0
github.com/lmittmann/tint v1.1.3
github.com/luthermonson/go-proxmox v0.4.0
github.com/moby/moby/api v1.54.2
github.com/moby/moby/client v0.4.1
github.com/neilotoole/slogt v1.1.0
Expand Down Expand Up @@ -33,6 +34,7 @@ require (
dario.cat/mergo v1.0.2 // indirect
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/buger/goterm v1.0.4 // indirect
github.com/bytedance/gopkg v0.1.3 // indirect
github.com/bytedance/sonic v1.15.0 // indirect
github.com/bytedance/sonic/loader v0.5.0 // indirect
Expand All @@ -45,7 +47,9 @@ require (
github.com/containerd/platforms v1.0.0-rc.1 // indirect
github.com/cpuguy83/dockercfg v0.3.2 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/diskfs/go-diskfs v1.7.0 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/djherbis/times v1.6.0 // indirect
github.com/docker/go-connections v0.7.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/ebitengine/purego v0.10.0 // indirect
Expand All @@ -69,13 +73,16 @@ require (
github.com/goccy/go-yaml v1.19.2 // indirect
github.com/google/gnostic-models v0.7.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jinzhu/copier v0.3.4 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.18.5 // indirect
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect
github.com/magefile/mage v1.14.0 // indirect
github.com/magiconair/properties v1.8.10 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
Expand Down
Loading
Loading