PHP Composer Private Packages via Satis and Repman

Khimananda Oli 8 min read Web Development
PHP Composer Private Packages via Satis and Repman

By Khimananda Oli | Last reviewed: August 2026

Managing internal libraries across multiple projects becomes unmanageable without a dedicated registry, forcing teams to rely on fragile Git URLs or public exposure. Implementing PHP Composer private packages via Satis and Repman solves this by providing a secure, authenticated, and performant mirror for your proprietary code. This guide covers the architectural decisions, configuration steps, and security hardening required to run a production-grade private Packagist in 2026.

How do you choose between Satis and Repman for private packages?

The decision between Satis and Repman is rarely about features alone; it is about operational overhead versus flexibility. Before configuring CI/CD best practices for small teams, you must select the right foundation. Satis is essentially a static site generator for Composer metadata. It scans your configured Git repositories, builds JSON index files, and exits. There is no database, no web interface, and no persistent daemon. This makes it incredibly stable and easy to host on simple object storage or Nginx, but it lacks user management and real-time updates.

Repman, conversely, is a full-featured application built with Symfony. It provides a web UI for managing repositories, supports multiple authentication methods per organization, and handles proxying of public Packagist automatically. For teams managing more than five private repositories or requiring granular access control, Repman reduces the friction that eventually forces Satis users to write custom wrapper scripts. However, it introduces PHP runtime dependencies, a database requirement, and background workers.

Satis (Static) vs Repman (Dynamic)Satis WorkflowGit ReposCron / CIJSON FilesNginx / S3Repman WorkflowWeb UISymfony AppDatabaseDist Cache
Architectural difference: Satis generates static metadata periodically, while Repman serves dynamic responses via a persistent application stack.
FeatureSatisRepman
Setup ComplexityLow (Single binary/container)Medium (App + DB + Worker)
User ManagementNone (HTTP Basic only)Built-in (Roles, Tokens, OAuth)
Update MechanismCron / Webhook triggeredReal-time / Background Queue
Public ProxyManual ConfigurationAutomatic Fallback
Resource UsageNegligible (Idle)Moderate (Persistent RAM)
Best For<10 Repos, Single TeamMulti-team, Enterprise, Audit

How do you configure Satis for automated private repository indexing?

Satis remains the industry standard for lean operations. In practice, most issues stem from misconfigured SSH keys or missing webhook triggers rather than Satis itself. To set up PHP Composer private packages via Satis effectively, treat the configuration as infrastructure code. Do not edit satis.json manually on the server; version control it alongside your deployment manifests.

Defining the Repository Configuration

Your satis.json defines what gets indexed. A common mistake is listing every single branch. Instead, filter tags to reduce build time and storage usage. When integrating with GitHub Actions or GitLab CI, ensure the runner has read-only SSH access to all listed repositories.

{
    "name": "internal-packages",
    "homepage": "https://packages.internal.example.com",
    "repositories": [
        { "type": "vcs", "url": "[email protected]:myorg/core-lib.git" },
        { "type": "vcs", "url": "[email protected]:myorg/billing-sdk.git" }
    ],
    "require-all": true,
    "archive": {
        "directory": "dist",
        "format": "zip",
        "prefix-url": "https://packages.internal.example.com"
    },
    "config": {
        "secure-http": true
    }
}

Automating Builds with Webhooks

Relying solely on cron jobs creates a lag between merging code and having it available for deployment. Configure your Git provider to send push events to a lightweight webhook receiver that triggers satis build. This ensures that PHP Composer private packages via Satis are available within seconds of a tag push. If you are using Docker, mount the output directory to a volume served by Nginx, ensuring the web server never executes PHP directly.

How do you deploy Repman for multi-team package management?

When your organization grows beyond a single engineering team, the lack of visibility in Satis becomes a bottleneck. Repman fills this gap by providing a centralized dashboard where team leads can add repositories without touching server configs. Deploying Repman requires a standard LEMP stack or Docker Compose setup, but the operational payoff is significant for compliance-heavy environments.

Initial Setup and Organization Structure

Repman organizes packages into Organizations. This maps cleanly to business units or product lines. After installation via Composer or Docker, create separate organizations for "Core Platform," "Client Projects," and "Experimental." This isolation prevents junior developers from accidentally depending on unstable experimental libraries in production applications. Refer to Kubernetes secrets management if deploying Repman in a cluster to handle database credentials securely.

Configuring Authentication Proxies

Repman excels at handling upstream authentication. Instead of distributing SSH keys to every developer, Repman uses its own credentials to fetch from GitHub/GitLab and serves packages via token-based auth. Developers authenticate once against Repman, and Repman handles the upstream complexity. This centralization simplifies offboarding; revoking a user's Repman account instantly cuts access to all private packages.

DeveloperRepman ServerGitHub / GitLab1. composer require (Token)2. Fetch Source (SSH Key)3. Return Zip/Meta4. Serve Cached PackageSecurity BoundaryDeveloper never touches upstream Git credentials.Repman caches dists locally for resilience.
Repman acts as an authentication proxy, shielding upstream Git credentials and caching artifacts for faster local installs.

How do you secure private Composer registries in production?

Security for PHP Composer private packages via Satis and Repman extends beyond HTTPS. You must enforce strict access controls and validate supply chain integrity. In my experience auditing SOC 2 environments, package registries are frequently overlooked attack vectors. Treat your private registry with the same rigor as your production database.

  • Enforce Token Rotation: Never use long-lived passwords. Configure Repman to issue API tokens with expiration dates. For Satis, rotate HTTP Basic credentials quarterly via Ansible or Terraform.
  • Restrict Network Access: Your registry should not be publicly accessible unless necessary. Use VPC peering, Cloudflare Zero Trust, or IP allowlists to restrict access to known office IPs and CI runners.
  • Enable Checksum Verification: Ensure composer.json in consuming projects includes checksums. Both Satis and Repman generate SHA-256 hashes automatically. Composer verifies these by default, preventing man-in-the-middle tampering.
  • Audit Access Logs: Enable access logging on the web server fronting your registry. Unusual patterns, such as bulk downloads at 3 AM or requests from unknown IPs, often indicate compromised credentials.
  • Sign Your Tags: Encourage GPG signing for library releases. While Composer doesn't enforce signature verification natively yet, maintaining signed tags prepares you for future supply chain security standards like SLSA.

How do you integrate private packages into CI/CD pipelines?

Consuming private packages in CI differs from local development. Developers have interactive auth; pipelines do not. Injecting credentials safely is critical. Never commit auth.json to version control. Instead, use your CI platform's secret management to inject tokens at runtime. For those exploring handling secrets in CI/CD pipelines safely, the pattern remains consistent: environment variables mapped to Composer's expected auth format.

Configuring Auth in GitHub Actions

Create a step that generates auth.json dynamically before running composer install. This keeps secrets out of the filesystem history. Use the official Composer action or a simple shell command to write the file.

- name: Configure Private Repo Auth
  run: |
    mkdir -p ~/.composer
    echo '{"http-basic":{"packages.internal.example.com":{"username":"token","password":"${{ secrets.COMPOSER_TOKEN }}"}}}' > ~/.composer/auth.json
    
- name: Install Dependencies
  run: composer install --prefer-dist --no-interaction

Optimizing Pipeline Performance

Private registries can become bottlenecks if not cached. Enable Composer's cache directory in your CI configuration. For Repman users, leverage the built-in proxy cache to avoid hitting upstream Git providers repeatedly during parallel test runs. If using Satis, ensure the dist archive generation is enabled; downloading pre-built zips is significantly faster than cloning Git repositories in ephemeral CI containers.

Package Not Found?Auth Configured?(auth.json / Token)NOAdd CredentialsYESRepo Added toSatis/Repman?NORegister Repo &Trigger RebuildYESCheck Version Constraints
Troubleshooting flowchart for resolving common authentication and indexing failures in private Composer registries.

Implementing Sustainable Private Package Infrastructure

Successfully managing PHP Composer private packages via Satis and Repman requires matching the tool to your organizational maturity. Start with Satis if you need a zero-maintenance solution for a handful of libraries. Migrate to Repman when user management, audit trails, or multi-team isolation become necessary. Regardless of choice, prioritize automated credential injection in CI, enforce HTTPS everywhere, and treat your registry as a critical production dependency. If your team needs assistance designing a compliant, scalable package infrastructure, reach out to discuss your specific requirements.

Frequently Asked Questions

Satis is a static metadata generator requiring cron jobs, while Repman is a dynamic PHP application offering a web UI, proxy caching, and organization management out of the box.

Add the repository URL under the repositories key in composer.json with type set to composer. Ensure authentication credentials are stored securely in auth.json or environment variables.

Yes. Repman caches public packages locally, reducing external API calls and speeding up installs during Packagist outages or network restrictions in air-gapped environments.

Yes. Satis receives security patches but lacks active feature development. Teams needing modern UIs or proxying should consider Repman instead.

Use HTTP basic auth or SSH keys. Store credentials in auth.json, never in version control. Restrict server access via firewall rules and TLS encryption.

Yes. Repman integrates natively with GitHub, GitLab, and Bitbucket OAuth providers, enabling automatic repository syncing and user-based access control without manual token management.

Usually caused by missing repository definitions, incorrect version constraints, or unauthenticated access. Verify repositories config, run composer diagnose, and check auth.json credentials match the server.

Absolutely. Official Docker images exist for Repman. Mount volumes for persistent storage, configure environment variables for database and OAuth, and expose port 8080 behind a reverse proxy.

Run satis build every five to fifteen minutes via cron. Frequent rebuilds ensure new tags appear quickly but increase server load; adjust based on team commit velocity.

Repman supports local filesystem, AWS S3, and MinIO. Configure via environment variables. S3-compatible storage enables scalable artifact hosting across distributed infrastructure teams.

Export your Satis satis.json repository list, import into Repman via CLI or UI, update composer.json endpoints, and rotate credentials. Test resolution before decommissioning Satis.

Yes. Repman downloads and stores zip archives and metadata locally after first fetch, serving subsequent requests directly without hitting upstream VCS providers repeatedly.

No. Satis only supports VCS and Composer-type repositories. Monorepos require splitting into separate repos or using Repman which handles path symlinks during local development.

Repman requires PHP 8.3 or higher. Ensure your runtime matches this minimum and that required extensions like intl, zip, and pdo_pgsql are installed and enabled.

Run composer install with verbose flag to inspect HTTP responses. Check server logs for 401 errors, validate auth.json format, and confirm tokens have not expired or been revoked.