Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

TeamCity CI: Getting Started

By Kokil Thapa | Last reviewed: September 2026

Your team picked JetBrains TeamCity because builds need to be fast, visible, and dependable. TeamCity CI: Getting Started is where most teams stall: the UI looks friendly, yet the first green build still feels far away. I've maintained GitLab CI and Deployer pipelines on production Laravel apps for years. TeamCity solves a different problem—deep build history, reusable templates, and first-class .NET and PHP tooling in one server. This guide walks you from blank server to a working pipeline with real commands, config snippets, and the mistakes I see on client projects that treat CI as an afterthought. For broader pipeline context, see our Laravel GitLab CI step-by-step guide.

How Do You Get Started with TeamCity CI?

TeamCity is a self-hosted CI server from JetBrains. You run a central server and one or more build agents. The server stores configuration, queues jobs, and serves the web UI. Agents execute builds on machines you control—on-prem VMs, cloud instances, or Docker containers.

The onboarding path has four milestones. Each one should produce a visible result before you move on.

  1. Install the TeamCity server and open the web UI on port 8111.
  2. Register a build agent on the same host or a separate machine.
  3. Create a project, attach a Git VCS root, and add build steps.
  4. Run the first build, inspect logs, then add tests and deploy hooks.

Do not wire production deploy on day one. Get checkout, dependency install, and unit tests green first. That matches how I roll out CI on custom Laravel applications: prove the build, then add gates.

TeamCity CI: Getting Started — Core ArchitectureGit RemoteGitLab / GitHubTeamCity ServerUI + queue + configPort 8111Build AgentPHP + ComposerFirst Build PipelineCheckout → Composer install → PHPUnit → ArtefactsTrigger: VCS hook or manual Run
TeamCity CI getting started flow: VCS triggers the server, which assigns work to an agent running your build steps.

What Hardware and Software Do You Need Before Installing TeamCity?

TeamCity runs on Linux, Windows, or macOS. For production Laravel CI, Ubuntu 22.04 or 24.04 on a VPS is the path I recommend. It matches the stacks described in our Linux system administration service and keeps PHP versions predictable.

Server sizing for small teams

A team of five to fifteen developers can start with 2 vCPU, 4 GB RAM, and 40 GB SSD for the TeamCity server alone. Build agents need separate resources—at least 2 vCPU and 4 GB RAM per agent running PHP 8.3+ and Composer 2.10. Shared hosting will not work; you need shell access and outbound Git access.

Software prerequisites on the agent

  • PHP 8.3 or 8.4 (Laravel 12 needs PHP 8.2+; Laravel 13 needs PHP 8.3+)
  • Composer 2.10
  • Git 2.x
  • Node.js 26 LTS if you compile front-end assets with Vite 8.x
  • MySQL 8.4 or PostgreSQL 18 client libraries for integration tests

Install TeamCity using the official tarball or Docker image from JetBrains TeamCity installation documentation. Docker is fine for evaluation. Production teams often prefer a managed VM with persistent data and logs directories on separate volumes.

Quick Linux install via tarball

# On Ubuntu 24.04 — download current TeamCity server bundle from JetBrains
sudo mkdir -p /opt/teamcity /var/teamcity
cd /opt/teamcity
sudo tar xzf TeamCity-*.tar.gz --strip-components=1

# Run under a dedicated user
sudo useradd -r -s /bin/false teamcity
sudo chown -R teamcity:teamcity /opt/teamcity /var/teamcity

# systemd unit (simplified)
sudo tee /etc/systemd/system/teamcity.service <<'EOF'
[Unit]
Description=TeamCity Server
After=network.target

[Service]
User=teamcity
ExecStart=/opt/teamcity/bin/teamcity-server.sh run
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl enable --now teamcity

Open http://your-server:8111, accept the licence, and create the admin account. The first-run wizard also installs a bundled agent on the same machine—useful for smoke tests, not for heavy parallel builds.

How Do You Create Your First TeamCity Build Pipeline?

TeamCity organises work into projects and build configurations. A project maps to a product or repo. A build configuration is one pipeline—main CI, release, or nightly.

Step 1: Create the project and VCS root

In the UI, choose Create ProjectFrom a repository URL. Paste your Git HTTPS or SSH URL. TeamCity probes branches and suggests a default. For SSH, upload a deploy key under Administration → SSH Keys.

Set checkout rules explicitly. A common Laravel rule checks out the default branch plus pull-request refs if you add a feature-branch build later:

# VCS checkout rule example in TeamCity UI
+:refs/heads/*
-:refs/heads/dependabot/**

Step 2: Add build steps

For a Laravel 12 app, define these build steps in order:

  1. Command Linecomposer install --no-interaction --prefer-dist --optimize-autoloader
  2. Command Linecp .env.ci .env && php artisan key:generate
  3. Command Linephp artisan migrate --force --env=testing (when a test DB is available)
  4. Command Linephp artisan test --parallel or vendor/bin/pest
  5. Command Linenpm ci && npm run build (optional artefact step)

Mark step 1–4 as required. Fail fast on Composer lock drift—never use composer update in CI.

Step 3: Configure triggers and parameters

Add a VCS Trigger so every push to main queues a build. Define system properties the agent resolves at runtime:

# Build parameters (Name → Value)
env.PHP_BIN=/usr/bin/php8.3
env.COMPOSER_MEMORY_LIMIT=512M
teamcity.build.checkoutDir=%system.teamcity.build.checkoutDir%

Use Snapshot dependencies when one configuration must consume artefacts from another—for example, a package build that feeds a deploy build. That pattern mirrors artefact promotion in blue-green deployment pipelines.

First TeamCity Build ConfigurationVCS TriggerCheckoutGit cloneComposervendor/PHPUnitPest testsBuild Features to Add NextComposer cache · Node modules cache · JUnit reportCoverage gate · Artefact: public/buildFail build on test regression
A minimal TeamCity pipeline for PHP: trigger, checkout, Composer install, then PHPUnit or Pest with optional caches and coverage gates.

How Do You Connect TeamCity to Git and Run Laravel Builds?

Version control integration is where TeamCity earns its keep. The server polls or receives webhooks, maps commits to configurations, and shows a per-commit status graph you can share with stakeholders.

Webhook vs polling

Prefer webhooks for GitLab or GitHub. Polling adds delay and load. In GitLab, add a webhook pointing to:

https://teamcity.example.com/app/hooks/github

TeamCity documents provider-specific URLs in the VCS hosting integration guide. Use a read-only deploy token scoped to the single repository.

Agent-friendly Laravel CI script

Keep a .teamcity/ci.sh script in the repo so local runs match CI:

#!/usr/bin/env bash
set -euo pipefail

export APP_ENV=testing
export DB_CONNECTION=sqlite
export DB_DATABASE=":memory:"

composer install --no-interaction --prefer-dist
php artisan config:clear
php artisan test --parallel

Point the TeamCity step to bash .teamcity/ci.sh. Developers on macOS or WSL can run the same file before push. Validate JSON env files with our JSON formatter tool when generating CI secrets payloads.

Build chains on real projects

On booking platforms like Adventure Third Pole Trek, CI must run migrations, feature tests, and sometimes asset builds. Split heavy suites across configurations: fast-check on every push, full-suite nightly. Use parallel test runs with ParaTest inside the agent to cut wall-clock time.

Enable the XML report processing build feature for PHPUnit JUnit output:

php artisan test --log-junit build/report.xml

TeamCity surfaces failed tests in the Overview tab. That beats scrolling raw console logs when a suite has hundreds of cases.

TeamCity CI vs GitLab CI vs Jenkins: Which Should You Pick?

Teams often compare TeamCity against tools they already run. The right choice depends on hosting model, language mix, and who maintains the server.

CriterionTeamCityGitLab CIJenkins
HostingSelf-hosted server + agentsGitLab.com or self-managed GitLabSelf-hosted controller + agents
Config styleUI, Kotlin DSL, versioned settings.gitlab-ci.yml in repoJenkinsfile Groovy or UI
PHP/Laravel ergonomicsStrong via command steps and cachesNative in repos I deploy with Deployer 7Flexible but plugin-heavy upkeep
Build insightsExcellent history, test triage, investigationsGood; depends on tier and runnersVaries widely by plugin set
Licensing costFree up to 100 configs; paid beyondFree tier + paid runners/minutesOpen source; infra labour is the cost
Best fitMixed stacks, JetBrains shops, deep build analyticsGitLab-centric teams, YAML-native workflowsMaximum plugin ecosystem, legacy estates

If your organisation already lives in GitLab, read our GitHub Actions vs GitLab CI comparison before adding another server. TeamCity shines when builds are complex, multi-platform, or you need granular test history without gluing plugins together.

CI Platform Decision MatrixTeamCityDeep build historyKotlin DSL + UIBest analyticsGitLab CIYAML in repoGit + CI unifiedBest Git-nativeJenkinsPlugin ecosystemGroovy pipelinesHighest upkeepChoose TeamCity whenMixed .NET + PHP · Need investigation UI · Self-hosted agentsAlready on JetBrains toolchain
TeamCity CI vs GitLab CI vs Jenkins: pick TeamCity when build visibility and multi-stack agents matter more than all-in-one Git hosting.

How Do You Harden TeamCity with Caches, Secrets, and Quality Gates?

A green hello-world build is not production CI. The next layer prevents slow pipelines, leaked tokens, and silent regressions.

Dependency caching

Add a shared cache directory on the agent for Composer and npm. TeamCity cache rules key off composer.lock and package-lock.json hashes. See build caching strategies to speed up CI for key naming patterns that also work in TeamCity cache configs.

# Example cache path on Linux agent
/home/teamcity/.cache/composer
/home/teamcity/.cache/npm

Secrets management

Never store production DB passwords in plain build parameters. Use TeamCity project-level parameters marked Password, or connect HashiCorp Vault / AWS Secrets Manager via integrations. Rotate deploy keys quarterly. Our secrets in CI/CD pipelines guide applies directly—mask values in logs and scope tokens per environment.

Quality gates

Add build failure conditions:

  • Test count must not drop compared to last successful build.
  • Code coverage must not fall below a threshold (see code coverage gates in CI).
  • Static analysis step with zero new blocker issues.

Wire SonarQube or PHPStan as a dedicated step. Fail the build on regression, not on legacy debt you have not scheduled yet.

Kotlin DSL for configuration as code

Export project settings to a .teamcity/ directory in your repository. Commit Kotlin DSL so changes go through review:

// Simplified Kotlin DSL — buildType block
object MainCi : BuildType({
    id("MyProject_MainCi")
    name = "Main CI"
    vcs {
        root(MyProject_HttpsGit)
    }
    steps {
        script {
            name = "Run tests"
            scriptContent = "bash .teamcity/ci.sh"
        }
    }
    triggers {
        vcs {
            branchFilter = "+:refs/heads/main"
        }
    }
})

Kotlin DSL is the escape hatch when click-ops drift appears. It pairs well with the verification patterns in build verification and quality gates.

Production TeamCity HardeningCachesComposer + npm keyed by lockfilesSecretsPassword params · scoped tokensQuality GatesCoverage · tests · static analysisKotlin DSLVersioned .teamcity/ in GitAgent Security BaselineDedicated user · firewall · separate deploy keysSee self-hosted runner hardening guides
After TeamCity CI getting started, add caches, masked secrets, quality gates, and Kotlin DSL before linking production deploy steps.

For agent isolation guidance, follow self-hosted CI runner security practices. TeamCity agents face the same SSH-key and supply-chain risks as GitLab runners or Jenkins nodes.

Deploy step (after CI is stable)

Only after tests and gates pass should you add deploy. On VPS targets I still use Deployer 7 from a final step:

composer install --no-dev --optimize-autoloader
vendor/bin/dep deploy production --branch=main

That mirrors the flow in deploy Laravel with GitLab CI to a VPS, swapped into a TeamCity script step. Sister legal-tech sites on shared EC2—such as Notary Kathmandu—benefit from identical deploy scripts regardless of CI front-end.

If you evaluate Azure DevOps alongside JetBrains, compare with Azure Pipelines first pipeline guide. For Jenkins-heavy estates, our Jenkins CI/CD tutorial shows equivalent stages.

Database migration safety belongs in CI discussion too. Run migrations against disposable schemas in CI, never production. Read database migrations in CI/CD pipelines before automating schema changes on deploy.

Static analysis fits cleanly as a pre-test step. Integrate the workflow from static code analysis in CI with SonarQube when stakeholders want trend lines, not one-off lint runs.

When pipelines grow noisy, add secrets scanning with Gitleaks as an early build step. It catches accidental .env commits before tests even start.

For Pest-based suites, align reporting with Laravel testing with Pest in CI/CD. The JUnit exporter works the same under TeamCity.

Ongoing maintenance—agent OS patches, PHP minor upgrades, disk monitoring—maps to support and maintenance services if your team lacks dedicated ops headcount.

Test regex-heavy validation rules locally with the regex tester before encoding them in CI scripts.

Learn more about my background on the about me page, or browse the full project portfolio for Laravel systems that run automated pipelines in production.

Key Takeaways

  • Install TeamCity server, register a dedicated agent with PHP 8.3+ and Composer 2.10, then prove checkout and tests before adding deploy.
  • Model each pipeline as a build configuration with explicit VCS rules, shell steps, and JUnit report processing for PHPUnit or Pest.
  • Use webhooks instead of polling, keep a shared .teamcity/ci.sh, and split fast vs nightly builds as test suites grow.
  • Add Composer/npm caches, masked password parameters, and coverage or test-count gates before calling the pipeline production-ready.
  • Export Kotlin DSL to Git when UI changes accumulate—treat CI config like application code.
  • TeamCity CI: Getting Started is complete only when agents are patched, secrets rotated, and deploy steps idempotent on rollback.

People Also Ask

Is TeamCity free for small teams?

JetBrains offers a free licence for up to 100 build configurations and three build agents. That covers many Laravel products until you add multiple environments, platforms, or long build matrices. Beyond those limits you need a commercial licence keyed to agent count.

Can TeamCity build pull requests from GitLab or GitHub?

Yes. Add a VCS root, enable branch specifications for merge-request or pull-request refs, and attach a VCS trigger with a branch filter. TeamCity posts commit status back to the provider when you configure a connection and use the REST API or bundled integration.

Does TeamCity replace Deployer or GitLab CI for Laravel deploys?

No. TeamCity orchestrates when builds and deploys run. Deployer, Envoy, or shell scripts still perform the release on your VPS or cloud host. Many teams keep GitLab for source hosting and add TeamCity when they outgrow simple YAML pipelines or need richer test analytics.

How do you speed up slow TeamCity PHP builds?

Cache Composer and npm directories on agents, run tests in parallel with ParaTest, use snapshot dependencies instead of rebuilding artefacts, and pin agents to PHP versions so opcache stays warm between runs. Disable Xdebug unless a dedicated coverage configuration needs it.

Ship Your First TeamCity Pipeline with Confidence

TeamCity CI: Getting Started boils down to a reliable agent, a reproducible shell script, and gates that fail loudly. Install the server, wire Git, run Laravel tests, then layer caches and secrets before you touch production. The payoff is faster feedback and a build history your whole team can trust.

Need help standing up TeamCity agents beside an existing Laravel app, or migrating from Jenkins without downtime? Contact us to plan the pipeline, harden runners, and connect deploy steps that match how your team actually ships.

Frequently Asked Questions

TeamCity is a self-hosted continuous integration server from JetBrains. You run a central server that stores configuration and queues jobs, plus one or more build agents that execute builds on machines you control. Getting started has four milestones: install the server and open the web UI on port 8111, register a build agent, create a project with a Git VCS root and build steps, then run your first build and inspect logs. Do not wire production deploy on day one. Prove checkout, Composer install, and unit tests first—the same rollout pattern I use on custom Laravel applications before adding deploy hooks.

For production Laravel CI, Ubuntu 22.04 or 24.04 on a VPS is the practical path. A team of five to fifteen developers can start with 2 vCPU, 4 GB RAM, and 40 GB SSD for the TeamCity server alone. Build agents need separate resources—at least 2 vCPU and 4 GB RAM per agent running PHP 8.3 or 8.4 and Composer 2.10. Shared hosting will not work; you need shell access and outbound Git access. Agent software prerequisites include Git 2.x, Node.js 26 LTS if you compile front-end assets with Vite 8.x, and MySQL 8.4 or PostgreSQL 18 client libraries for integration tests.

Install using the official tarball or Docker image from JetBrains documentation. Docker suits evaluation; production teams often prefer a managed VM with persistent data and logs on separate volumes. On Ubuntu 24.04, download the server bundle, extract to /opt/teamcity, create a dedicated teamcity system user, set ownership on /opt/teamcity and /var/teamcity, then add a systemd unit pointing ExecStart to /opt/teamcity/bin/teamcity-server.sh run. Enable and start the service, open port 8111, accept the licence, and create the admin account. The first-run wizard can install a bundled agent on the same machine—fine for smoke tests, not heavy parallel builds.

TeamCity organises work into projects and build configurations. Create a project from your Git repository URL, set checkout rules explicitly—for example checking out refs/heads/ while excluding dependabot branches—and add build steps in order: composer install with --no-interaction --prefer-dist --optimize-autoloader, copy .env.ci to .env and run php artisan key:generate, run migrations against a test database when available, then php artisan test --parallel or vendor/bin/pest, and optionally npm ci followed by npm run build. Mark early steps as required and fail fast on Composer lock drift—never use composer update in CI. Add a VCS Trigger so every push to main queues a build.

Version control integration is where TeamCity earns its keep. The server polls or receives webhooks, maps commits to configurations, and shows a per-commit status graph. Prefer webhooks for GitLab or GitHub over polling, which adds delay and load. In GitLab, point a webhook to your TeamCity hooks URL documented in JetBrains VCS hosting integration guide. Use a read-only deploy token scoped to a single repository, or upload an SSH deploy key under Administration → SSH Keys. Keep a .teamcity/ci.sh script in the repo so local runs match CI, and enable XML report processing so PHPUnit or Pest JUnit output surfaces failed tests in the Overview tab.

JetBrains offers a free licence for up to 100 build configurations and three build agents. That covers many Laravel products until you add multiple environments, platforms, or long build matrices. Beyond those limits you need a commercial licence keyed to agent count.

The right choice depends on hosting model, language mix, and who maintains the server. TeamCity is self-hosted with UI, Kotlin DSL, and versioned settings—strong for mixed stacks, JetBrains shops, and deep build analytics. GitLab CI is native YAML in repos, ideal when your organisation already lives in GitLab; I deploy many Laravel apps with GitLab CI and Deployer 7. Jenkins is open source and plugin-heavy, suited to legacy estates needing maximum extensibility. TeamCity shines when builds are complex or multi-platform and you want granular test history without gluing plugins together. If you are GitLab-centric, adding another server may not be worth the ops overhead.

A green hello-world build is not production CI. Add shared cache directories on agents for Composer and npm, keyed off composer.lock and package-lock.json hashes. Never store production database passwords in plain build parameters—use project-level parameters marked Password, or connect HashiCorp Vault or AWS Secrets Manager, and rotate deploy keys quarterly. Add build failure conditions: test count must not drop versus the last successful build, code coverage must not fall below a threshold, and static analysis with PHPStan or SonarQube must show zero new blocker issues. Fail on regression, not legacy debt you have not scheduled. Export Kotlin DSL to .teamcity/ in Git when UI click-ops starts drifting.

Yes. Add a VCS root for your repository, then configure branch specifications so TeamCity detects feature branches and pull-request refs alongside your default branch. Set checkout rules explicitly—for example including refs/heads/ while excluding dependabot branches if you add dependabot later. Pair branch specs with a VCS Trigger or webhook so pushes and opened merge requests queue builds without polling delay. Use a read-only deploy token or SSH deploy key scoped to the single repository. Split heavy test suites across configurations: fast-check on every push, full-suite nightly, mirroring how I run CI on booking platforms with large Laravel test suites.

Define these steps in order for a Laravel 12 application. First, composer install --no-interaction --prefer-dist --optimize-autoloader—never composer update in CI. Second, cp .env.ci .env and php artisan key:generate so the app boots in a testing context. Third, php artisan migrate --force --env=testing when a disposable test database is available; run migrations against test schemas, never production. Fourth, php artisan test --parallel or vendor/bin/pest, exporting JUnit XML via --log-junit build/report.xml for TeamCity test triage. Optionally add npm ci and npm run build when Vite 8.x assets must compile. Mark steps one through four as required so the build fails fast.

Only after tests, caches, masked secrets, and quality gates pass consistently. Do not wire production deploy on day one. Once the pipeline is stable, add a final script step that runs composer install --no-dev --optimize-autoloader followed by vendor/bin/dep deploy production --branch=main using Deployer 7—the same pattern I use from GitLab CI on VPS targets. Sister legal-tech sites on shared EC2 benefit from identical deploy scripts regardless of which CI front-end queues the job. Ensure deploy steps are idempotent on rollback, and read up on database migration safety before automating schema changes during deploy.

Kotlin DSL lets you export project settings to a .teamcity/ directory in your repository and commit configuration as code. A buildType block defines the VCS root, shell script steps such as bash .teamcity/ci.sh, and VCS triggers with branch filters like +:refs/heads/main. Use it when UI-based click-ops starts drifting and CI changes need the same review process as application code. It pairs well with build verification and quality gate patterns because diffs are visible in pull requests. Kotlin DSL is the escape hatch—not day-one setup—but it becomes essential once multiple environments, build chains, and snapshot dependencies accumulate across a growing Laravel monorepo.

Prefer webhooks for GitLab or GitHub. Polling adds delay and unnecessary load on both TeamCity and your Git host. With webhooks, pushes and merge-request events reach TeamCity immediately at URLs documented in the JetBrains VCS hosting integration guide—for example pointing a GitLab webhook to your TeamCity hooks endpoint. Combine webhooks with explicit VCS checkout rules and branch specifications so only intended refs trigger builds. Use a read-only deploy token scoped to the repository rather than a personal access token tied to one developer. This setup gives stakeholders a per-commit status graph without waiting for the next poll cycle.

Add a shared cache directory on each build agent for Composer and npm artefacts. TeamCity cache rules key off composer.lock and package-lock.json hashes, so a lockfile change invalidates stale dependencies automatically. Typical Linux agent paths include /home/teamcity/.cache/composer and /home/teamcity/.cache/npm. Without caching, every build re-downloads vendor and node_modules, which wastes minutes on PHP 8.3 projects with large dependency trees. Caching belongs in the hardening layer after your first green build—not before you prove checkout and tests work. Pair caches with parallel test runs using ParaTest to cut wall-clock time further on agents with at least 2 vCPU and 4 GB RAM.

Never store production database passwords or API tokens in plain build parameters visible in the UI or logs. Use TeamCity project-level parameters marked as Password so values are masked, or connect HashiCorp Vault or AWS Secrets Manager through TeamCity integrations. Scope deploy keys and read-only Git tokens to a single repository and rotate them quarterly. Add Gitleaks as an early build step to catch accidental .env commits before tests run. The same principles from general secrets-in-CI guidance apply: mask values in logs, separate credentials per environment, and treat CI configuration like application code once you export Kotlin DSL. Agents face the same SSH-key and supply-chain risks as GitLab runners or Jenkins nodes.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: