Skip to main content

Getting Started

Set up the Launchpad GitHub Action to automatically deploy Docker/OCI images as containers on MIE's Proxmox cluster.

Prerequisites

  • A Docker/OCI image published to a container registry (GHCR, Docker Hub, etc.)
  • An API key for the create-a-container server (request one from your site admin)

Repository Secrets

Add these secrets in your repository's Settings > Secrets and variables > Actions:

SecretDescription
LAUNCHPAD_API_KEYAPI key for the create-a-container server
LAUNCHPAD_API_URLBase URL of the create-a-container server

Action Inputs

InputRequiredDefaultDescription
api_keyYesBearer token for authenticating with the create-a-container API
api_urlYesBase URL of the create-a-container server
template_nameNoDocker/OCI image reference to deploy (e.g., ghcr.io/org/app:tag). Omit to delete the container.
container_env_varsNoEnvironment variables to set inside the container (JSON string, e.g., '{"NODE_ENV": "production"}')
servicesNoServices configuration (JSON array)
site_idNo1Site ID for the container management system

Supported Workflow Events

EventAction
pushCreates or locates the container for the branch
createCreates a container for the new branch
pull_request (opened/synchronize/reopened)Creates or locates the container for the PR head branch
pull_request (closed)Deletes the container
deleteDeletes the container for the deleted branch

Basic Usage

- uses: mieweb/launchpad@main
with:
api_key: ${{ secrets.LAUNCHPAD_API_KEY }}
api_url: ${{ secrets.LAUNCHPAD_API_URL }}
template_name: ghcr.io/your-org/your-app:latest

PR Preview Environments

Deploy preview containers on pull requests and clean them up automatically when the PR closes. This is the most common pattern:

name: PR Preview

on:
pull_request:
types: [opened, synchronize, reopened, closed]

jobs:
deploy-preview:
if: github.event.action != 'closed'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: mieweb/launchpad@main
with:
api_key: ${{ secrets.LAUNCHPAD_API_KEY }}
api_url: ${{ secrets.LAUNCHPAD_API_URL }}
template_name: ghcr.io/your-org/your-app:pr-${{ github.event.pull_request.number }}

cleanup-preview:
if: github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: mieweb/launchpad@main
with:
api_key: ${{ secrets.LAUNCHPAD_API_KEY }}
api_url: ${{ secrets.LAUNCHPAD_API_URL }}

When template_name is omitted (as in cleanup-preview), the action removes the container associated with the current branch or PR.

Complete Example: Build + Deploy

This example builds a Docker image, pushes it to GHCR, and deploys a preview container — all triggered by PR events:

name: Build and Deploy Preview

on:
pull_request:
types: [opened, synchronize, reopened, closed]

env:
REGISTRY: ghcr.io

jobs:
build-and-push:
if: github.event.action != 'closed'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4

- uses: docker/setup-buildx-action@v3

- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- uses: docker/metadata-action@v5
id: meta
with:
images: ${{ env.REGISTRY }}/${{ github.repository }}
tags: |
type=ref,event=pr

- uses: docker/build-push-action@v6
with:
push: true
tags: ${{ steps.meta.outputs.tags }}

deploy-preview:
if: github.event.action != 'closed'
needs: build-and-push
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: mieweb/launchpad@main
with:
api_key: ${{ secrets.LAUNCHPAD_API_KEY }}
api_url: ${{ secrets.LAUNCHPAD_API_URL }}
template_name: ${{ env.REGISTRY }}/${{ github.repository }}:pr-${{ github.event.pull_request.number }}

cleanup-preview:
if: github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: mieweb/launchpad@main
with:
api_key: ${{ secrets.LAUNCHPAD_API_KEY }}
api_url: ${{ secrets.LAUNCHPAD_API_URL }}

Container Access

After deployment, you'll receive access details located in your containers page on manager.os.mieweb.org including:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Container ID : 136
Internal IP : 10.15.129.23
Domain Name : https://my-app-main.os.mieweb.org
SSH Access : ssh -p 2344 user@my-app-main.os.mieweb.org
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

SSH

ssh -p <port> <username>@<hostname>.os.mieweb.org

Docker Image Requirements

Your Docker image must:

  1. Be publicly accessible — The create-a-container server pulls images anonymously. If your image is on GHCR, go to Package settings > Danger Zone > Change visibility > Public.
  2. EXPOSE ports — Declare which ports your application listens on
  3. Use the org.mieweb.opensource-server.services.http.default-port label — Specify the primary HTTP port for reverse proxy configuration
EXPOSE 3000
LABEL org.mieweb.opensource-server.services.http.default-port=3000

The create-a-container server reads these from the image metadata to configure networking and reverse proxy rules automatically.

Troubleshooting

Action fails with authentication error:

  • Verify LAUNCHPAD_API_KEY secret is set correctly
  • Confirm the API key hasn't been revoked

Deploy step runs but skips container creation:

  • Check the workflow output for the "Create or Locate Container" step — if it's missing, the action version may not support your event type
  • Ensure you're using the latest version of mieweb/launchpad@main
  • Verify the workflow includes the correct on: triggers for your use case

Container not accessible after deploy:

  • Wait 1-2 minutes for background provisioning to complete
  • Verify your Docker image exposes the correct port
  • Check that the default-port label matches your application's listen port

Container creation fails with HTTP 401: authentication required:

  • The Docker image is private. The server pulls images without credentials, so the package must be public.
  • On GHCR: go to https://github.com/users/<owner>/packages/container/<image>/settingsDanger ZoneChange visibilityPublic

Image not found:

  • Ensure the Docker image was pushed successfully before the deploy step
  • Verify the image tag matches between the build and deploy jobs