Deployment guide

Concourse CI

Overview

Concourse CI is an open-source continuous integration and continuous delivery system built on one idea: everything is a pipeline. You declare pipelines as plain YAML made of resources, jobs and tasks, and keep them under version control alongside your code. Every build runs in a clean container, so builds are reproducible and there is no snowflake build server to maintain.

This SecureAnyCloud image installs Concourse CI 8.2.4 on Ubuntu 24.04 LTS as a complete single-node deployment: the web node (the ATC API, the web UI and the TSA worker gateway), one worker that runs your task containers, and a PostgreSQL database.

What you get:

  • Concourse CI 8.2.4 (web and worker) and the fly command-line client
  • PostgreSQL backing the Concourse ATC, with its data directory on a dedicated data disk
  • The web UI published on port 80 through an nginx reverse proxy, with WebSocket upgrade for live build logs
  • A dedicated Azure data disk at /var/lib/concourse for the PostgreSQL cluster and the worker work-dir
  • A unique admin password and a freshly rotated session signing key, generated on the first boot of every VM and written to a root-only credentials file
  • concourse-web.service, concourse-worker.service, postgresql.service and nginx.service as enabled, active systemd units
  • 24/7 SecureAnyCloud support

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.

Standard_B4ms (4 vCPU / 16 GiB RAM) is a good starting size, because Concourse runs the web node, the worker and PostgreSQL on one VM.

Configure the network security group (NSG) to allow inbound 22/tcp from your management network and 80/tcp for the web UI. For public exposure, put TLS in front of the UI (see Enabling HTTPS).

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Concourse CI by SecureAnyCloud, and select Create.

On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80).

Review the dedicated data disk on the Disks tab, then select Review + create and Create.

Step 2 - Deploy from the Azure CLI

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:concourse-ci-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name concourse-ci \
  --image sac1647283583153:concourse-ci-ubuntu-24-04:default:latest \
  --size Standard_B4ms \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name concourse-ci --port 80 --priority 1010

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

On first boot, the VM generates a unique admin password, rotates the Concourse session signing key, and then starts the web node, the worker and PostgreSQL. Confirm that all four services are active:

systemctl is-active concourse-web.service concourse-worker.service postgresql.service nginx.service

Each line reports active.

Step 5 - Check the Concourse info endpoint

The Concourse ATC exposes an unauthenticated info endpoint that returns the running version as JSON. nginx proxies it on port 80. Query it:

curl -s http://127.0.0.1/api/v1/info | jq .

The expected output reports version 8.2.4:

{ "version": "8.2.4", "worker_version": "2.5", "feature_flags": { "build_rerun": false, "cache_streamed_volumes": false, "global_resources": false, "resource_causality": false }, "external_url": "http://10.0.0.4", "cluster_name": "sac" }

nginx also serves a static health endpoint that does not depend on the upstream. Query it:

curl -s http://127.0.0.1/health

It returns ok.

Step 6 - Retrieve your admin password

Your VM generates a unique admin password on first boot and writes it to a root-only file. Read it with sudo:

sudo cat /root/concourse-ci-credentials.txt

This file contains CONCOURSE_URL, CONCOURSE_ADMIN_USER (admin) and CONCOURSE_ADMIN_PASSWORD. Store the password somewhere safe. It grants full administrative access to the main team.

Step 7 - Sign in to the web UI

Open http://<vm-public-ip>/ in a browser. Click login, choose the main team, and sign in as admin with the password from Step 6. The dashboard shows your teams and pipelines.

Step 8 - Log in with the fly CLI

fly is the Concourse command-line client. It is preinstalled at /usr/local/bin/fly. Confirm that its version matches the server:

fly --version

It prints 8.2.4.

Log in to a target named ci. Replace <CONCOURSE_ADMIN_PASSWORD> with your admin password from Step 6:

fly -t ci login -c http://127.0.0.1:8080 -u admin -p <CONCOURSE_ADMIN_PASSWORD>

You should see target saved. Then list the registered workers. One worker reports running:

sudo HOME=/root fly -t ci workers

Step 9 - Set and trigger a pipeline

Create a minimal pipeline file:

cat > /tmp/hello-world.yml <<'YML' jobs: - name: hello-world plan: - task: say-hello config: platform: linux image_resource: type: registry-image source: { repository: busybox } run: path: echo args: ["hello from sac concourse"] YML

Set the pipeline non-interactively with -n, then unpause it:

sudo HOME=/root fly -t ci set-pipeline -p hello -c /tmp/hello-world.yml -n
sudo HOME=/root fly -t ci unpause-pipeline -p hello

The pipeline now appears on the dashboard. Trigger the job from the web UI, or run fly -t ci trigger-job -j hello/hello-world --watch. The first run pulls the busybox image, runs the task in a fresh container and prints the build log live.

Step 10 - Where data lives

PostgreSQL (the Concourse database) and the worker work-dir both live on a dedicated Azure data disk mounted at /var/lib/concourse. The disk is separate from the OS disk and can be resized independently. Check the mount:

df -h /var/lib/concourse

Every VM created from this image gets a newly provisioned disk.

Enabling HTTPS

The image serves the Concourse web UI over plain HTTP on port 80. For production, put TLS in front of it with your own domain. Point a DNS record at the VM public IP, then install a certificate with certbot and the nginx plugin. Replace your-domain.example.com with your hostname:

sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.com

After enabling TLS, set CONCOURSE_EXTERNAL_URL=https://your-domain.example.com/ in /etc/concourse/web.env. Then restart concourse-web.service so that generated links and fly login use HTTPS.

Maintenance

The Concourse and fly binaries live under /opt/concourse and /usr/local/bin/fly. Configuration is in /etc/concourse. To view logs, run:

sudo journalctl -u concourse-web.service --no-pager | tail -20

PostgreSQL is the stock Ubuntu package and receives security updates through unattended-upgrades. To back up your Concourse database, run pg_dump against the atc database as the postgres user. To restart the stack, run sudo systemctl restart concourse-web.service concourse-worker.service.

Support

SecureAnyCloud maintains this image and provides 24/7 support. Concourse is a trademark of its respective owners. SecureAnyCloud packages and supports the open-source distribution and is not affiliated with the Concourse project.

Deploy on Azure

Launch Concourse CI on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure