> ## Documentation Index
> Fetch the complete documentation index at: https://developer.upsun.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploying open-source projects on Upsun: Snipe-IT as an example

> Learn how to deploy any GitHub-hosted open-source project on Upsun by forking repositories, configuring for deployment, and keeping your fork synchronized with upstream updates.

export const PostMeta = ({data = {}}) => {
  const {author, date, image} = data;
  const authors = Array.isArray(author) ? author : author ? [author] : [];
  const resolveAuthor = slug => {
    const entry = AUTHOR_MAP[slug] || ({});
    const name = entry.name || slug;
    const github = entry.github || null;
    const linkedin = entry.linkedin || null;
    const url = github ? `https://github.com/${github}` : linkedin || null;
    const avatarUrl = github ? `https://github.com/${github}.png?size=64` : null;
    return {
      name,
      url,
      avatarUrl
    };
  };
  const formattedDate = date ? new Date(date).toLocaleDateString('en-US', {
    year: 'numeric',
    month: 'long',
    day: 'numeric'
  }) : null;
  if (!image && authors.length === 0 && !formattedDate) return null;
  const AUTHOR_MAP = {
    "aaron-collier": {
      "name": "Aaron Collier"
    },
    "aaron-dudenhofer": {
      "name": "Aaron Dudenhofer"
    },
    "aaron-porter": {
      "name": "Aaron Porter"
    },
    "adriaan-odendaal": {
      "name": "Adriaan Odendaal"
    },
    "ajmal": {
      "name": "Ajmal Siddiqui"
    },
    "akalipetis": {
      "name": "Antonis Kalipetis"
    },
    "alexander-varwijk": {
      "name": "Alexander Varwijk"
    },
    "alicia-bevilacqua": {
      "name": "Alicia Bevilacqua"
    },
    "amelie-deguerry": {
      "name": "Amelie Deguerry"
    },
    "anacidre": {
      "name": "Ana Cidre",
      "linkedin": "https://www.linkedin.com/in/ana-cidre"
    },
    "andoni": {
      "name": "Andoni Auzmendi"
    },
    "andrei-taranu": {
      "name": "Andrei (Alex) Taranu",
      "linkedin": "https://www.linkedin.com/in/andrei-alex-taranu/"
    },
    "andrew-baxter": {
      "name": "Andrew Baxter"
    },
    "andrew-melck": {
      "name": "Andrew Melck"
    },
    "antoine-crochet-damais": {
      "name": "Antoine Crochet Damais"
    },
    "augustin-delaporte": {
      "name": "Augustin Delaporte",
      "linkedin": "https://www.linkedin.com/in/augustindelaporte/"
    },
    "branislav-bujisic": {
      "name": "Branislav Bujisic"
    },
    "carl-smith": {
      "name": "Carl Smith"
    },
    "caroline-leroy": {
      "name": "Caroline Leroy"
    },
    "cati-mayer": {
      "name": "Cati Mayer"
    },
    "catplat": {
      "name": "C Trinkwon"
    },
    "ceelolulu": {
      "name": "Celeste van der Watt"
    },
    "chadwcarlson": {
      "name": "Chad Carlson",
      "github": "chadwcarlson",
      "linkedin": "https://www.linkedin.com/in/chadwcarlson"
    },
    "chris-ward": {
      "name": "Chris Ward"
    },
    "chris-yates": {
      "name": "Chris Yates"
    },
    "christian-sieber": {
      "name": "Christian Sieber"
    },
    "christopher-lockheardt": {
      "name": "Christopher Lockheardt"
    },
    "christopher-skene": {
      "name": "Christopher Skene"
    },
    "chuck-morgan": {
      "name": "Chuck Morgan"
    },
    "corey-dockendorf": {
      "name": "Corey Dockendorf"
    },
    "crell": {
      "name": "Crell"
    },
    "damz": {
      "name": "Damz"
    },
    "dan-morrison": {
      "name": "Dan Morrison"
    },
    "davidbonachera": {
      "name": "David Bonachera",
      "github": "davidbonachera",
      "linkedin": "https://www.linkedin.com/in/davidbonachera"
    },
    "dereliahmet1": {
      "name": "Ahmet Faruk Dereli"
    },
    "devicezero": {
      "name": "Jonas Kröger",
      "github": "devicezero",
      "linkedin": "https://www.linkedin.com/in/jonaskroeger/"
    },
    "doug-goldberg": {
      "name": "Doug Goldberg"
    },
    "duncan-naves": {
      "name": "Duncan Naves",
      "github": "duncannaves",
      "linkedin": "https://www.linkedin.com/in/duncan-naves-a94423aa"
    },
    "erika-bustamante": {
      "name": "Erika Bustamante"
    },
    "fabpot": {
      "name": "Fabien Potencier"
    },
    "flovntp": {
      "name": "Florent Huck",
      "github": "flovntp",
      "linkedin": "https://www.linkedin.com/in/florenthuck"
    },
    "fred-plais": {
      "name": "Fred Plais"
    },
    "gauthier-garnier": {
      "name": "Gauthier Garnier"
    },
    "gilzow": {
      "name": "Paul Gilzow"
    },
    "gmoigneu": {
      "name": "Guillaume Moigneu",
      "github": "gmoigneu",
      "linkedin": "https://www.linkedin.com/in/guillaumemoigneu/"
    },
    "gregqualls": {
      "name": "Greg Qualls"
    },
    "guguss": {
      "name": "Augustin Delaporte"
    },
    "haylee-millar": {
      "name": "Haylee Millar"
    },
    "ivana-kotur": {
      "name": "Ivana Kotur"
    },
    "jackrabbithanna": {
      "name": "Mark Hanna"
    },
    "jared-wright": {
      "name": "Jared Wright",
      "github": "jww-sh",
      "linkedin": "https://www.linkedin.com/in/jaredwaynewright"
    },
    "jessica-orozco": {
      "name": "Jessica Orozco"
    },
    "joey-stanford": {
      "name": "Joey Stanford"
    },
    "john-grubb": {
      "name": "John Grubb"
    },
    "jonas-kruger": {
      "name": "Jonas Kruger"
    },
    "kathryn-frazer": {
      "name": "Kathryn Frazer"
    },
    "kemiojo": {
      "name": "Kemi Elizabeth Ojogbede"
    },
    "kieronsambrook-smith": {
      "name": "Kieronsambrook Smith"
    },
    "laurent-arnoud": {
      "name": "Laurent Arnoud"
    },
    "letoya-boyne": {
      "name": "Letoya Boyne"
    },
    "lolautruche": {
      "name": "Jérôme Vieilledent"
    },
    "lyly-lepinay": {
      "name": "Lyly Lepinay"
    },
    "manauwar-alam": {
      "name": "Manauwar Alam"
    },
    "marc-antoine-porri": {
      "name": "Marc Antoine Porri"
    },
    "maria-antinkaapo": {
      "name": "Maria Antinkaapo"
    },
    "maria-de-anton": {
      "name": "Maria De Anton"
    },
    "mark-dorison": {
      "name": "Mark Dorison"
    },
    "markus-hausammann": {
      "name": "Markus Hausammann"
    },
    "mary-thomas": {
      "name": "Mary Thomas"
    },
    "mathias-bolt-lesniak": {
      "name": "Mathias Bolt Lesniak"
    },
    "mathieu-strauch": {
      "name": "Mathieu Strauch"
    },
    "matthias-van-woensel": {
      "name": "Matthias Van Woensel",
      "linkedin": "https://www.linkedin.com/in/matthias-van-woensel-267a069"
    },
    "michael-sharp": {
      "name": "Michael Sharp"
    },
    "mupsi": {
      "name": "Marine Gandy"
    },
    "natalie-harper": {
      "name": "Natalie Harper"
    },
    "ngommenginger": {
      "name": "Nicolas Gommenginger",
      "linkedin": "https://www.linkedin.com/in/nicolas-gommenginger"
    },
    "nicholas-bennison": {
      "name": "Nicholas Bennison"
    },
    "nicholas-vahalik": {
      "name": "Nicholas Vahalik"
    },
    "nick-hardiman": {
      "name": "Nick Hardiman"
    },
    "nickanderegg": {
      "name": "Nickanderegg"
    },
    "nicolas-grekas": {
      "name": "Nicolas Grekas",
      "github": "nicolas-grekas",
      "linkedin": "https://www.linkedin.com/in/nicolasgrekas/"
    },
    "niti-malwade": {
      "name": "Niti Malwade"
    },
    "opensocialteam": {
      "name": "Opensocialteam"
    },
    "ori-pekelman": {
      "name": "Ori Pekelman"
    },
    "otavio-santana": {
      "name": "Otavio Santana"
    },
    "palwandi": {
      "name": "Pawan Alwandi",
      "github": "pawpy",
      "linkedin": "https://www.linkedin.com/in/pawanalwandi"
    },
    "patrick-boest": {
      "name": "Patrick Boest"
    },
    "patrick-dawkins": {
      "name": "Patrick Dawkins",
      "github": "pjcdawkins",
      "linkedin": "https://www.linkedin.com/in/patrickdawkins"
    },
    "patrick-klima": {
      "name": "Patrick Klima"
    },
    "pjcdawkins": {
      "name": "Pjcdawkins"
    },
    "prineet-kaurbhurji": {
      "name": "Prineet Kaurbhurji"
    },
    "quentin-sinig": {
      "name": "Quentin Sinig"
    },
    "ralt": {
      "name": "Florian Margaine",
      "github": "ralt",
      "linkedin": "https://www.linkedin.com/in/florian-margaine-43971136"
    },
    "ramanathanramakrishnamurthy": {
      "name": "Ramanathanramakrishnamurthy"
    },
    "remi-lejeune": {
      "name": "Rémi Lejeune"
    },
    "ribel": {
      "name": "Taras Kruts"
    },
    "robert-douglass": {
      "name": "Robert Douglass"
    },
    "rudy-weber": {
      "name": "Rudy Weber"
    },
    "ryan-hicks": {
      "name": "Ryan Hicks"
    },
    "sabri-helal": {
      "name": "Sabri Helal"
    },
    "savannah-bergeron": {
      "name": "Savannah Bergeron"
    },
    "shannon-vettes": {
      "name": "Shannon Vettes"
    },
    "shawn-ogasawara": {
      "name": "Shawn Ogasawara",
      "linkedin": "https://www.linkedin.com/in/shawn-ogasawara-83a9a0/"
    },
    "shawna-spoor": {
      "name": "Shawna Spoor"
    },
    "shedrack-akintayo": {
      "name": "Shedrack Akintayo"
    },
    "simon-ruggier": {
      "name": "Simon Ruggier"
    },
    "sophie-van-der-kindere": {
      "name": "Sophie Van Der Kindere"
    },
    "stefanos-thampis": {
      "name": "Stefanos Thampis"
    },
    "stephen-weinberg": {
      "name": "Stephen Weinberg"
    },
    "sukhman-virk": {
      "name": "Sukhman Virk"
    },
    "sumaira-nazir": {
      "name": "Sumaira Nazir"
    },
    "sumer": {
      "name": "Sümer Cip"
    },
    "syed-raza": {
      "name": "Syed Raza"
    },
    "tamara-bacchia": {
      "name": "Tamara Bacchia"
    },
    "tara-arnold": {
      "name": "Tara Arnold"
    },
    "theosakamg": {
      "name": "Mickael Gaillard",
      "github": "theosakamg"
    },
    "thomasdiluccio": {
      "name": "Thomas di Luccio"
    },
    "tim-anderson": {
      "name": "Tim Anderson"
    },
    "tom-helmer-hansen": {
      "name": "Tom Helmer Hansen"
    },
    "tylermills": {
      "name": "Tyler Mills"
    },
    "upsun": {
      "name": "Upsun"
    },
    "veronika-tolkachova": {
      "name": "Veronika Tolkachova",
      "linkedin": "https://www.linkedin.com/in/veronika-tolkachova-169167a2"
    },
    "vince-parker": {
      "name": "Vince Parker"
    },
    "vinnie-russo": {
      "name": "Vincenzo Russo"
    },
    "vrobert78": {
      "name": "Vincent Robert",
      "github": "vrobert78",
      "linkedin": "https://www.linkedin.com/in/vincent-robert-498a883"
    },
    "yuriy-babenko": {
      "name": "Yuriy Babenko"
    },
    "yuriy-gerasimov": {
      "name": "Yuriy Gerasimov"
    }
  };
  return <div className="post-meta">
      {(authors.length > 0 || formattedDate) && <div className="post-meta-info">
          {authors.length > 0 && <div className="post-meta-authors">
              {authors.map(slug => {
    const {name, url, avatarUrl} = resolveAuthor(slug);
    const inner = <>
                    {avatarUrl && <img src={avatarUrl} alt={name} className="post-meta-avatar" />}
                    <span className="post-meta-author-name">{name}</span>
                  </>;
    return url ? <a key={slug} href={url} target="_blank" rel="noopener noreferrer" className="post-meta-author">
                    {inner}
                  </a> : <span key={slug} className="post-meta-author">{inner}</span>;
  })}
            </div>}
          {authors.length > 0 && formattedDate && <span className="post-meta-separator" aria-hidden="true">·</span>}
          {formattedDate && <span className="post-meta-date">{formattedDate}</span>}
        </div>}
      {image && <img src={image} alt="" className="post-meta-image" aria-hidden="true" />}
    </div>;
};

<PostMeta data={{ author: ["gmoigneu"], date: "2025-10-07T00:00:00+00:00", image: "/images/posts/tutorials/deploying-open-source-on-upsun/deploying-open-source-on-upsun.webp" }} />

Deploying open-source projects on cloud platforms is not as easy as it seems, especially when you want to customize the application while staying current with upstream updates. The **fork-and-deploy** approach offers the perfect balance: you get full control over your deployment while maintaining the ability to pull in security patches and new features from the original project.

This guide demonstrates how to deploy any GitHub-hosted open-source project on Upsun using [Snipe-IT](https://github.com/grokability/snipe-it) (an IT asset management system built with Laravel) as our example. The principles and techniques apply to most open-source web applications, regardless of their technology stack.

## What you'll learn

* Fork and configure open-source projects for Upsun deployment
* Adapt application configuration for cloud deployment
* Manage environment variables and service dependencies
* Keep your fork synchronized with upstream changes
* Deploy production-ready open-source applications

## Prerequisites

Before starting, ensure you have:

* An [Upsun account](https://upsun.com) with an active project
* A [GitHub account](https://github.com)
* Basic familiarity with Git and command line operations
* [Upsun CLI](https://docs.upsun.com/administration/cli.html#1-install) installed locally

## Forking the target repository

Start by creating your own fork of the open-source project you want to deploy. This gives you full control over the codebase while maintaining the ability to pull updates from the original project.

Using Snipe-IT as our example:

1. Navigate to the [Snipe-IT repository](https://github.com/grokability/snipe-it) on GitHub
2. Click the **Fork** button in the top-right corner
3. Choose your GitHub account as the destination
4. Wait for GitHub to create your fork

Once forked, clone your repository locally:

```bash {filename="Terminal"} theme={null}
git clone https://github.com/YOUR_USERNAME/snipe-it.git
cd snipe-it
```

**For other projects**: Replace the repository URL with your target open-source project. The forking process remains identical across all GitHub repositories.

## Adding Upsun configuration

Every application needs specific configuration to run on Upsun. We'll create the necessary configuration files to define our application, services, and deployment process.

The configuration approach varies by technology stack, but the core concepts remain the same. Here's how to configure a Laravel application (Snipe-IT), with notes on adapting for other frameworks.

### Create the Upsun configuration

Create the `.upsun/config.yaml` file in your repository root. This example shows a Laravel/PHP configuration, but adapt the runtime, extensions, and build process for your specific technology stack:

```yaml {filename=".upsun/config.yaml"} theme={null}
applications:
  snipeit:
    type: php:8.2
    source:
      root: "/"
    
    runtime:
      extensions:
        - redis
        - pdo_mysql
        - gd
        - ldap
        - zip
        - bcmath

    relationships:
      database: "database:mariadb"
      cache: "cache:redis"
    
    web:
      locations:
        "/":
          root: "public"
          passthru: "/index.php"
          index:
            - "index.php"
          expires: -1
          scripts: true
          allow: false
          rules:
            \.php$:
              allow: true
        "/storage":
          root: "storage/app/public"
          expires: 1y
          scripts: false
          allow: true
    
    mounts:
      "storage/app":
        source: storage
        source_path: app
      "storage/logs":
        source: storage
        source_path: logs
      "storage/framework/cache":
        source: storage
        source_path: cache
      "storage/framework/sessions":
        source: storage
        source_path: sessions
      "storage/framework/views":
        source: storage
        source_path: views
      "bootstrap/cache":
        source: storage
        source_path: bootstrap
    
    hooks:
      build: |
        set -e
        composer install --no-dev --optimize-autoloader
        npm ci
        npm run build
        
      deploy: |
        set -e
        php artisan config:cache
        php artisan route:cache
        php artisan view:cache
        php artisan migrate --force
        php artisan storage:link

services:
  database:
    type: mariadb:11.8

  cache:
    type: redis-persistent:7.0

routes:
  "https://www.{default}/":
    type: redirect
    to: "https://{default}/"
  
  "https://{default}/":
    type: upstream
    upstream: "snipeit:http"
```

**Key configuration concepts:**

* **Runtime**: Specify your application's language and version (php:8.2, node:18, python:3.11, etc.)
* **Extensions**: Add required language extensions for your application
* **Services**: Define databases, caches, and other dependencies
* **Build/Deploy hooks**: Commands to build assets and initialize the application
* **Mounts**: Writable directories for user uploads, logs, and cache files

### Create environment configuration

Create a `.environment` file to map Upsun service variables to your application's expected format. This example shows Laravel environment mapping:

```bash {filename="Terminal"} theme={null}
# Database configuration
export DB_CONNECTION="mysql"
export DB_HOST="$DATABASE_HOST"
export DB_PORT="$DATABASE_PORT"
export DB_DATABASE="$DATABASE_PATH"
export DB_USERNAME="$DATABASE_USERNAME"
export DB_PASSWORD="$DATABASE_PASSWORD"

# Cache configuration
export CACHE_DRIVER="redis"
export REDIS_HOST="$CACHE_HOST"
export REDIS_PORT="$CACHE_PORT"
export REDIS_PASSWORD="$CACHE_PASSWORD"
export REDIS_URL="redis://${CACHE_HOST}:${CACHE_PORT}"

# Session configuration
export SESSION_DRIVER="redis"
export SESSION_CONNECTION="default"

# Queue configuration (optional)
export QUEUE_CONNECTION="redis"

# Email configuration
export MAIL_DRIVER="smtp"
export MAIL_HOST="$PLATFORM_SMTP_HOST"
export MAIL_PORT="25"
export MAIL_ENCRYPTION=""
```

**For other frameworks:**

* **Django**: Map to `DATABASE_URL`, `REDIS_URL`, etc.
* **Node.js/Express**: Set `DATABASE_URL`, `REDIS_URL`, `PORT`, etc.
* **Rails**: Configure `DATABASE_URL`, `REDIS_URL`, `RAILS_ENV`, etc.
* **WordPress (Bedrock)**: Map to `DB_HOST`, `DB_USER`, `DB_PASSWORD`, `WP_CACHE_KEY_SALT`, etc.

### Commit the configuration

Add and commit your new configuration files:

```bash {filename="Terminal"} theme={null}
git add .upsun/config.yaml .environment
git commit -m "Add Upsun deployment configuration"
git push origin master
```

**Note**: Most projects use `main` instead of `master` as the default branch. Adjust accordingly.

## Creating your Upsun project

Now create a new Upsun project and connect it to your GitHub repository.

### Using the Upsun Console

1. Log in to the [Upsun Console](https://console.upsun.com)
2. Click **Create Project**
3. Choose **Import from GitHub**
4. Select your forked Snipe-IT repository
5. Choose your preferred region (select green regions for extra discounts)
6. Configure your project settings:
   * **Project name**: Give your project a descriptive name
   * **Production branch**: `master` or `main` (depending on your repository)
   * **Build and deploy immediately**: Check this option

<Note>
  If this is your first time using our GitHub integration, you will redirected to authorize the Upsun GitHub app to access your desired repositories.
</Note>

### Using the CLI (Alternative)

Alternatively, create the project using the Upsun CLI:

```bash {filename="Terminal"} theme={null}
# From your local project directory
upsun login
upsun project:create --title="Snipe-It" --region=us-3.platform.sh --default-branch=master
```

<Note>
  Please notice with use the `--default-branch=master` flag as the Snipe-IT GitHub project still uses `master` instead of the new default `main`.
</Note>

## Configuring environment variables

Most open-source applications require environment variables for proper operation. The specific variables depend on your application, but common categories include app configuration, database connections, API keys, and feature flags.

Here are examples for Snipe-IT (Laravel), with notes on what to adapt for other applications:

### Generating application secrets

Many applications require unique keys or secrets. For Laravel applications like Snipe-IT, generate the APP\_KEY locally:

```bash {filename="Terminal"} theme={null}
# Clone locally and generate key
composer install
cp .env.example .env
php artisan key:generate --show
```

Use the generated key in your `APP_KEY` variable (see `<ARTISAN-KEY>` below).

**For other frameworks:**

* **Django**: Generate `SECRET_KEY` with `python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"`
* **Node.js**: Generate random strings for session secrets using crypto libraries
* **Rails**: Use `rails secret` to generate `SECRET_KEY_BASE`

### Essential variables

Set these variables at the project level:

```bash {filename="Terminal"} theme={null}
upsun variable:create --level project --prefix env --name APP_NAME --value="Snipe-IT"
upsun variable:create --level project --prefix env --sensitive true --name APP_KEY --value="<ARTISAN-KEY>"

upsun variable:create --level environment --environment master --prefix env --name APP_ENV --value="production"
upsun variable:create --level environment --environment master --prefix env --name APP_DEBUG --value="false"
upsun variable:create --level environment --environment master --prefix env --name LOG_LEVEL --value="warning"

# File upload settings
upsun variable:create --level project --prefix env --name PRIVATE_FILESYSTEM_DISK --value="local"
upsun variable:create --level project --prefix env --name PUBLIC_FILESYSTEM_DISK --value="local"

# Email settings
upsun variable:create --level project --prefix env --name MAIL_FROM_ADDR --value="noreply@yourdomain.com"
upsun variable:create --level project --prefix env --name MAIL_FROM_NAME --value="Snipe-IT"
```

## First deployment

If you are using the GitHub integration, Upsun will automatically trigger deployments based on your GitHub repository events. If not, you can start your first deployment:

1. **Via Console**: Navigate to your project and click **Deploy**
2. **Via Git**: Push changes to your master branch
3. **Via CLI**: Use `upsun redeploy`

Upsun will:

* Build your application with the appropriate package manager
* Compile frontend assets (if configured)
* Run database migrations and initialization scripts
* Configure services (databases, caches, etc.)
* Generate SSL certificates

The deployment typically takes 2 to 5 minutes depending on your application size. Monitor progress in the Upsun Console or with:

```bash {filename="Terminal"} theme={null}
upsun activity:list
```

## Accessing your deployment

Once deployed, access your application through the provided URL. Most open-source applications require initial setup:

**For Snipe-IT:**

1. Create your admin account
2. Configure company settings
3. Set up asset categories and models
4. Configure LDAP (if needed)
5. Customize appearance and branding

**For other applications:** Check the project's documentation for first-run setup instructions. Common steps include creating admin accounts, running database seeds, or configuring integrations.

## Adding a custom domain

For production use, add your custom domain:

1. In the Upsun Console, go to **Domains**
2. Click **Add Domain**
3. Enter your domain name
4. Configure DNS with the provided CNAME record
5. Wait for SSL certificate provisioning

## Keeping your fork updated

Open-source projects receive regular updates for security patches, bug fixes, and new features. Keep your fork synchronized to benefit from these improvements:

### Setting up upstream remote

```bash {filename="Terminal"} theme={null}
# Add the original repository as upstream (replace with your project's URL)
git remote add upstream https://github.com/grokability/snipe-it

# Verify remotes
git remote -v
```

### Syncing updates

Regularly sync with upstream changes. Thanks to Upsun, you can preview and test these updates to avoid any issue with breaking changes:

```bash {filename="Terminal"} theme={null}
# Fetch latest changes from upstream
git fetch upstream

# Switch to your master branch
git checkout -b test-ugrade

# Merge upstream changes
git merge upstream/master

# Push updates on a new Upsun preview environment:
git push upsun test-upgrade
# or with the GitHub integration:
git push origin test-upgrade
```

### Handling conflicts

If you've customized the application, you may encounter merge conflicts during sync:

1. **Review conflicts**: Use `git status` to identify conflicted files
2. **Resolve manually**: Edit files to resolve conflicts
3. **Test changes**: Ensure functionality remains intact
4. **Commit resolution**: `git add .` and `git commit`

### Automated sync with GitHub Actions

Consider automating upstream sync with GitHub Actions:

```yaml {filename=".github/workflows/sync-upstream.yml"} theme={null}
name: Sync Upstream
on:
  schedule:
    - cron: '0 2 * * 1'  # Weekly on Monday at 2 AM
  workflow_dispatch:

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Sync upstream changes
        run: |
          git remote add upstream https://github.com/ORIGINAL-OWNER/PROJECT-NAME.git
          git fetch upstream
          git merge upstream/master
          git push origin master
```

## Getting help

* Check your project's official documentation
* Review [Upsun documentation](https://docs.upsun.com) for platform-specific issues
* Search the project's GitHub issues for similar problems
* Join project-specific community forums or the [Upsun Discord server](https://discord.com/invite/platformsh/)
* Check framework-specific resources (Laravel, Django, Rails, etc.)

## Conclusion

You now have your open-source application running on Upsun with a robust deployment pipeline. Your setup includes:

* Production-ready services (database, cache, etc.)
* SSL certificates and custom domain support
* Automated upstream synchronization strategy
* Scalable infrastructure that grows with your needs

This fork-and-deploy approach provides the perfect balance between customization control and staying current with upstream improvements. You can modify the application to fit your specific needs while easily pulling in security patches and new features from the original project.
