Seller Guide

Variations

Configure product variations with Docker Compose, system requirements, and advanced install options.

Variations define how your software gets installed on customer servers. Each variation has its own Docker Compose configuration, system requirements, and installation behavior. Use variations to offer different tiers or configurations of your product — for example, "Pied Piper - Basic", "Pied Piper - Pro", and "Pied Piper - Enterprise".

Go to your product's Variations tab and click Add Variation to get started.


Variation Details

Name

The variation name is shown to customers on their My Products page. Make it clear and descriptive — include both your product name and the tier so customers know exactly what they have access to.

GoodAvoid
Pied Piper - BasicBasic
Pied Piper - ProPro Edition
Pied Piper - Enterprisev1

Purchase Access

The Purchase Access section controls which payment products grant a customer access to this variation. You can link multiple products from different providers (Stripe, Lemon Squeezy) to the same variation.

Adding a product

Click Add Product to open the product picker. It loads all products from your connected payment integrations. Each product is labeled as One-time or Monthly/Yearly with its price.

Select a product, then configure Access Duration:

For subscription products — No duration to set. Access is tied to the subscription and revoked automatically when it ends. The table shows "While subscribed".

For one-time products — Choose how long access lasts after purchase:

OptionDescription
Expire after X daysAccess is revoked after the specified number of days
Never expiresCustomer keeps access permanently
For one-time lifetime products, choose Never expires. For annual license keys sold as one-time purchases, use Expire after 365 days and have customers repurchase to renew.

Multiple products

You can link the same variation to multiple products — for example, both a Stripe and a Lemon Squeezy listing. Customers who purchase through either provider get access. Each linked product can have its own access duration.


Image Tag Rules

The Image Tag Rules section controls which Docker image tags customers on this variation are allowed to pull from the registry. This lets you restrict access by tier — for example, "Pied Piper - Basic" customers can only pull v1.* tags while "Pied Piper - Pro" customers can pull everything.

Adding a rule

Click Add Rule and choose:

OptionDescription
All tagsCustomer can pull any image tag
Some tagsCustomer can only pull tags matching a pattern

For Some tags, enter a pattern using:

  • Exact tags: latest, 1.2.3
  • Wildcard (*): v1.* matches v1.0, v1.1, v1.2.3, etc.
The default rule * allows access to all tags. If you want to offer tiered access — for example, preventing Basic customers from pulling pro-* tagged images — remove the wildcard rule and add specific patterns for each variation.

Example: tiered tag access

VariationRuleAccess
Pied Piper - Basicv1.*Only v1 releases
Pied Piper - Pro*All releases including pro-* tags

Tags are checked when customers pull from the registry. If a pull request doesn't match any rule, it's denied.


Installation

System requirements

Set minimum server requirements. The install script checks these before proceeding and warns customers if their server doesn't meet them.

FieldDescription
CPU coresMinimum number of CPU cores
MemoryMinimum RAM in GB
Disk spaceMinimum free disk space in GB

Default image

Select which Docker image tag customers will install by default. This dropdown shows all images you've pushed to the registry for this product.

Docker Compose file

Enter your docker-compose.yml content. This file is downloaded to the customer's server during installation.

Self-Host Pro works with any framework or language that runs in Docker. Here are examples for popular stacks:

services:
  app:
    image: shpcr.io/your-team/your-product:latest
    ports:
      - "80:80"
      - "443:443"
    env_file:
      - .env
    volumes:
      - ./storage:/var/www/html/storage
    restart: unless-stopped

  database:
    image: postgres:16
    environment:
      - POSTGRES_DB=${DB_DATABASE}
      - POSTGRES_USER=${DB_USERNAME}
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    volumes:
      - db_data:/var/lib/postgresql/data
    restart: unless-stopped

  redis:
    image: redis:alpine
    restart: unless-stopped

volumes:
  db_data:
Use environment variables like ${APP_URL} in your compose file. These are loaded from the .env file you provide as a configuration file.

Prompt for install domain

When enabled, the install script:

  1. Detects the server's public IP address automatically
  2. Prompts the customer to confirm or enter a custom domain/IP
  3. Validates the URL format (supports IPv4, IPv6, and domain names)
  4. Writes APP_URL and APP_DOMAIN to the .env file

Example prompt the customer sees:

What URL will you use to access this application?
Examples:
  • Using IPv4 address:  https://192.168.1.100
  • Using IPv6 address:  https://[2001:db8::1]
  • Using domain name:   https://app.example.com

Press Enter to use: https://203.0.113.50 (automatically detected)

This is useful when your app needs to know its public URL for generating links, configuring SSL certificates, or setting CORS headers.

Configuration files

Add files that should be created in the project directory during installation. Common uses:

  • .env files with environment variables
  • Nginx or Traefik configuration
  • SSL certificates
  • Custom application config files

For each configuration file, you can set:

FieldDescription
File nameThe filename (e.g., .env, traefik.yml)
ContentsThe file contents
Permissionschmod value (e.g., 600 for sensitive files, 644 for readable files)
UID/GIDFile ownership — must match the user inside your Docker container
Prompt to editWhen enabled, opens the file in the customer's editor during install
Important: File ownership must match your container user. If your Docker container runs as a specific user (e.g., www-data, node, app), the UID/GID of mounted files must match that user's UID/GID inside the container. Otherwise, your application won't be able to read the files.Common UID/GID values:
  • www-data (PHP/Laravel): 82:82 or 33:33 depending on the base image
  • node (Node.js): 1000:1000
  • app (custom user): Check your Dockerfile
To find your container's user ID, run: docker run --rm your-image id

Example: .env file

Create a .env file that customers can customize during installation. Here are examples for different frameworks:

File name: .env

APP_NAME="My Application"
APP_ENV=production
APP_DEBUG=false
APP_URL=
APP_DOMAIN=

DB_CONNECTION=pgsql
DB_HOST=database
DB_PORT=5432
DB_DATABASE=app
DB_USERNAME=app
DB_PASSWORD=change-me-to-a-secure-password

MAIL_MAILER=smtp
MAIL_HOST=
MAIL_PORT=587
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_FROM_ADDRESS=

Permissions: 600 (owner read/write only — keeps secrets secure)

Prompt to edit: Yes

When "Prompt to edit" is enabled, the install script will:

  1. Download the file
  2. Ask the customer if they want to edit configuration files
  3. Open their default editor (nano, vim, etc.)
  4. Let them customize values before the application starts
If you enabled "Prompt for install domain", the install script automatically sets APP_URL and APP_DOMAIN in the .env file after the customer enters their URL.

Example: Traefik configuration

For applications using Traefik as a reverse proxy:

File name: traefik.yml

Contents:

api:
  dashboard: false

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
  websecure:
    address: ":443"

certificatesResolvers:
  letsencrypt:
    acme:
      email: ${ACME_EMAIL}
      storage: /letsencrypt/acme.json
      httpChallenge:
        entryPoint: web

providers:
  docker:
    exposedByDefault: false

Permissions: 644

Prompt to edit: No

Initialize commands

Commands that run after containers are created but before the application starts. Use these for:

  • Database migrations
  • Seeding initial data
  • Generating application keys
  • Running setup wizards
  • Creating admin users

Commands execute from the project directory (/srv/{product-slug}/) where your Docker Compose file and configuration files are located. You can run any system command — shell scripts, file operations, or system utilities.

To run commands inside your Docker containers, use docker compose run. Add commands in the order they should execute.

Examples by framework:

docker compose run --rm app php artisan key:generate --force
docker compose run --rm app php artisan migrate --force
docker compose run --rm app php artisan db:seed --force

Each command runs in sequence. If any command fails (non-zero exit code), the installation stops and shows an error.

Use the --rm flag to automatically remove the container after the command completes. Use --force, --noinput, or -n flags to skip interactive prompts since the install script runs non-interactively.
Commands run from /srv/{product-slug}/ with full access to system utilities. For example, you could run a sed command to modify a file. However, most initialization tasks are best performed inside your container for security and isolation.

Auto-start application after install

When enabled, the install script automatically runs docker compose up -d after:

  1. Downloading all files
  2. Configuring the domain (if enabled)
  3. Letting the customer edit files (if enabled)
  4. Running initialize commands (if configured)

When disabled, the install script downloads and configures everything but doesn't start the containers. The customer sees step-by-step instructions for starting manually. This is useful if you want customers to review configuration before starting.


How the install script works

When a customer runs the install command, here's what happens:

  1. System checks — Verifies Linux, root/sudo access, CPU, memory, and disk space
  2. Docker installation — Installs Docker if not present
  3. Project directory — Creates /srv/{product-slug}/
  4. Docker Compose file — Downloads your compose configuration
  5. Configuration files — Downloads additional files (.env, etc.)
  6. Domain prompt — Asks for URL and writes to .env (if enabled)
  7. Registry authentication — Logs into shpcr.io to pull your images
  8. File editing — Opens editor for files marked "Prompt to edit" (if enabled)
  9. Initialize commands — Runs your setup commands (if configured)
  10. Start application — Runs docker compose up -d (if enabled)

The customer sees colored output with progress indicators:

▸ Checking system requirements...
✓ CPU cores: 4 (minimum 1 required)
✓ Memory: 8192KB (minimum 524288KB required)
✓ Disk space: 50000000KB (minimum 1048576KB required)

▸ Configuring My App project...
ℹ Creating project directory: /srv/my-app
✓ Project directory created
ℹ Downloading docker-compose.yml...
✓ Downloaded and configured: docker-compose.yml
ℹ Downloading .env...
✓ Downloaded and configured: .env

▸ Configuring application access URL...
ℹ Detected server IP: 203.0.113.50
✓ Application URL set to: https://203.0.113.50

▸ Authenticating with Docker registry...
✓ Docker registry authentication successful

▸ Starting My App with Docker Compose...
ℹ Pulling latest Docker images...
✓ Images pulled successfully
ℹ Running initialization commands...
✓ Initialization completed successfully
✓ My App is now running!

Installation security

Self-Host Pro protects your software with multiple security measures during installation:

One-time use scripts

Each install script can only be used once. When a customer runs the script, it's marked as consumed and cannot be reused. This prevents script sharing and ensures each installation is authorized.

Short-lived scripts

Install scripts expire after 60 minutes. This limits the window of opportunity if a script URL is exposed.

IP address verification

When a customer generates an install script, Self-Host Pro captures their IP address. When the script is executed, the IP is recorded and associated with that installation. This creates an audit trail and helps identify unauthorized installation attempts.

Registry authentication

Docker images are served from a private registry (shpcr.io) that requires authentication. Customers must have valid access tokens to pull your images, and these tokens are tied to their purchase status. When a subscription expires or access is revoked, they can no longer pull updates.


Mirroring variations

When creating a new variation, you can set it to mirror another variation. Mirroring means the variation uses the source variation's install configuration at install time — this includes the Docker Compose file, configuration files, initialize commands, and installation options.

This is useful for offering multiple tiers that share the same underlying installation but differ in pricing or access rules. For example, "Pied Piper - Basic" and "Pied Piper - Pro" might install identically but give access to different Docker image tags.