Deployment guide

PipeCD 0.58.0

Overview

This guide shows how to launch and verify PipeCD 0.58.0 on Ubuntu 24.04 from SecureAnyCloud on Amazon EC2. The image is one version of the SecureAnyCloud Hardened Apache Subversion (SVN) & CI/CD Tools AMIs listing on AWS Marketplace. You select it as the software version when you launch.

PipeCD is an open-source GitOps continuous delivery platform (Apache-2.0 license, a CNCF project). You describe each application in a Git repository. PipeCD's agent, piped, watches the repository and deploys every change to its target, which can be Kubernetes, Amazon ECS, AWS Lambda, Terraform, Google Cloud Run or a plain script. Each deployment follows a pipeline of stages, approvals, analysis and automatic rollback. The control plane holds the projects, applications, deployments and their logs, and it serves the web console and the API.

What you get:

  • The PipeCD 0.58.0 control plane (server and ops) and piped, built on this image's build machine from upstream's source at tag v0.58.0 (commit dc6a6a9a), with a patched Go toolchain (go1.26.10) and semver-compatible security raises of Go modules. No source file is changed. The build recipe is on the instance in /usr/share/pipecd/build/.
  • The control plane's own datastore, filestore and cache, in containers on a private Docker network: MySQL 8.4.13 (Community, the official image with its OS packages upgraded), the versitygw 1.11.0 S3-compatible filestore (unprivileged) and Valkey 8.1.11, plus Envoy distroless-v1.40.2 as the control plane's gRPC-web gateway. Third-party images are pinned by digest.
  • One on-box piped, registered with this instance's control plane on first boot with its own key, and a demo application (sac-demo) in a local Git repository that it deploys once at first boot
  • Docker CE from Docker's official repository (its signing key pinned by fingerprint), configured so that no container can reach instance metadata, plus an egress chain that keeps every control-plane container off the network
  • nginx serving HTTPS on port 443 with a certificate created on your instance, and port 80 redirecting to HTTPS. The web console, the API (pipectl) and the piped service all use 443.
  • No default login. A per-instance static admin password, API key and piped key are created on first boot.
  • pipecd-set-hostname (serve PipeCD under your own DNS name), pipecd-webapi (a small helper for the web API) and pipecd-selftest (an end-to-end check that runs a real deployment)
  • Default user ubuntu, x86_64 architecture and a 40 GiB gp3 root volume
  • 24/7 SecureAnyCloud support

Security posture

  • No default login and no anonymous access. First boot creates the static administrator admin of the project SecureAnyCloud with a 24-character password made on your instance. Only its bcrypt hash is in the control plane's configuration. First boot also creates a READ_WRITE API key and the on-box piped's key. All of them are written only to /root/pipecd-credentials.txt (mode 0600, root). The web console's API, the API service and the piped service refuse callers without a session or a key, over both gRPC-web and native gRPC, and sign-in attempts are rate-limited per client address.
  • Per-instance secrets. The admin password, the API key, the piped key, PipeCD's encryption key for secrets management, the MySQL root and application passwords, the S3 filestore keys, the TLS key, the SSH host keys and the machine ID are all created on your instance, and no two instances share one. They reach the containers as root-only files, never on a command line.
  • The datastore, filestore and cache are private. MySQL, the S3 filestore and Valkey have no host port and sit on a private Docker network with the control plane. The control plane's gateway listens on 127.0.0.1:9090 only, so nginx is the only way in.
  • The control plane cannot reach instance metadata or your network. A rule in Docker's DOCKER-USER chain, applied before dockerd starts any container, refuses 169.254.169.254, fd00:ec2::254 and 168.63.129.16 for every container, so none can read the instance's IAM role credentials. A second chain refuses every connection that the control-plane containers start off their own networks, and all container IPv6.
  • piped can reach your VPC and the internet. piped is the part of PipeCD that deploys your applications, so it has to reach your Kubernetes API, Amazon ECS, AWS Lambda, Terraform providers and your Git servers. It is therefore allowed to connect to this instance's VPC and to the internet. It can never reach instance metadata, the Azure wireserver address, link-local addresses, the reserved and benchmark ranges (0.0.0.0/8, 192.0.0.0/24, 198.18.0.0/15, multicast 224.0.0.0/4 and 240.0.0.0/4) or this instance's other ports. Give the instance restrictive outbound security-group rules that allow only the targets piped deploys to, your Git server and the registries it needs. Give piped least-privilege credentials for each deployment target, and never an administrator role.
  • Hardened containers. Every container runs with all Linux capabilities dropped, no-new-privileges and core dumps off. No container is privileged, mounts the Docker socket or uses the host network. The control plane, piped and the filestore run as unprivileged users.
  • HTTPS from first boot. The image allows TLS 1.2 and 1.3 only and sends Strict-Transport-Security and a Secure, HttpOnly session cookie. The host name comes from configuration, never from a request. First boot reads the instance's public DNS name from EC2 instance metadata (IMDSv2) and pins nginx and PipeCD to it, and requests for any other host name get their connection closed. Cross-site state-changing requests are refused, and forged X-Forwarded-For, X-Real-IP and Forwarded headers never reach PipeCD.
  • Verified build. The source, the Go modules compiled into each binary and the container images were checked for licenses and scanned for known vulnerabilities before the build. SSH allows keys only, with no root login and no X11 forwarding. The AMI requires IMDSv2, and SSH host keys and the machine ID are generated fresh on every instance.

Trusted users only. A PipeCD user who can add or change an application decides what piped runs, and piped runs it with piped's network access and credentials. Give accounts, the API key and push access to the repositories piped watches only to people you trust with that. Keep ports 80 and 443 restricted to the networks that your users and your off-box pipeds work from.

Prerequisites

  • An AWS account and permission to launch EC2 instances
  • An EC2 key pair in the Region you launch in

Recommended instance type: m5.large (2 vCPUs, 8 GiB). The whole stack (MySQL, the object store, Valkey, the control plane, the gateways and piped) uses about 700 to 800 MiB of memory when idle.

We measured the stack on smaller burstable types. A t3.small (2 GiB) runs it with about 1.1 GiB still available. A t3.micro (1 GiB) starts and passes sudo pipecd-selftest, but it has only about 200 MiB left and no swap. For evaluation, the smallest size we recommend is t3.small. Real deployments run their tools inside piped, so use m5.large or larger for production.

Connecting to your instance

Connect over SSH as the ubuntu user, which is the default user for PipeCD 0.58.0 on Ubuntu 24.04 LTS.

1

Launch the instance

Option A: AWS Marketplace console

  • Open the SecureAnyCloud Hardened Apache Subversion (SVN) & CI/CD Tools AMIs listing on AWS Marketplace. Choose View purchase options, and then choose Subscribe. One subscription covers every version in the listing.
  • When the subscription is active, choose Launch your software.
  • Choose One-click launch from AWS Marketplace, or Launch from EC2 Console for the full launch wizard. In Version, choose PipeCD 0.58.0 on Ubuntu 24.04, and then choose your Region.
  • Pick an instance type (m5.large recommended) and your key pair.
  • Configure the security group. The listing's default group opens SSH (22), HTTP (80) and HTTPS (443). Restrict SSH to your own IP address, and restrict 80 and 443 to the networks that your users and any off-box pipeds work from. Never open 9090, 3306, 6379 or 7070. Replace the default "all traffic" outbound rule with rules for the targets piped deploys to (see the Security posture).
  • Choose your VPC and subnet. Under Advanced details, leave Metadata version at V2 only (the image already requires it) and set Metadata response hop limit to 1. With this setting, containers cannot reach instance metadata even without the image's own filter.
  • Choose Launch.

Option B: AWS CLI

Run the following commands on your own workstation. Replace the AMI ID with the one shown for your Region on the Marketplace launch page. Replace the VPC, subnet, key pair and CIDRs with your own:

SG=$(aws ec2 create-security-group --group-name pipecd \
  --description "PipeCD" --vpc-id vpc-0123456789abcdef0 \
  --query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 22 --cidr <your-mgmt-cidr>
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 443 --cidr <your-mgmt-cidr>
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 80 --cidr <your-mgmt-cidr>
aws ec2 run-instances \
  --image-id ami-0123456789abcdef0 \
  --instance-type m5.large \
  --key-name my-key-pair \
  --security-group-ids "$SG" \
  --subnet-id subnet-0123456789abcdef0 \
  --metadata-options HttpTokens=required,HttpPutResponseHopLimit=1,HttpEndpoint=enabled \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=pipecd}]'

A new security group allows all outbound traffic. To limit what piped can reach, remove that rule (aws ec2 revoke-security-group-egress --group-id "$SG" --ip-permissions IpProtocol=-1,IpRanges='[{CidrIp=0.0.0.0/0}]') and add one egress rule per deployment target, Git server and registry. Associate an Elastic IP if you want the address to survive a stop and start.

2

Connect and find your login

Connect as ubuntu with the key pair that you chose:

ssh -i ~/.ssh/my-key-pair.pem ubuntu@<public-ip>

First boot takes three to four minutes after the instance starts. It takes a little longer on the very first start, while EC2 reads the container images from their snapshot.

First boot sets the name that PipeCD is served as (the instance's public DNS name when it has one) and creates the TLS certificate and this instance's secrets. It then starts the datastore, filestore, cache and control plane, registers the on-box piped, deploys the demo application once and opens nginx.

The login is in a root-only file. The following commands show the address, the project, the user names and the field names without printing any password or key:

sudo grep -E '^pipecd\.(url|project|admin\.user|piped\.id|mysql\.(database|user))=' /root/pipecd-credentials.txt
sudo grep -oE '^[a-z.]+=' /root/pipecd-credentials.txt
sudo stat -c '%a %U:%G %n' /root/pipecd-credentials.txt
pipecd.url=https://ec2-203-0-113-25.compute-1.amazonaws.com/ pipecd.project=sac pipecd.admin.user=admin pipecd.piped.id=47238903-c6df-4cd3-9908-6b5eab90d34e pipecd.mysql.database=pipecd pipecd.mysql.user=pipecd pipecd.url= pipecd.project= pipecd.admin.user= pipecd.admin.pass= pipecd.api.key= pipecd.piped.id= pipecd.demo.app.id= pipecd.mysql.database= pipecd.mysql.user= pipecd.mysql.pass= 600 root:root /root/pipecd-credentials.txt

The credentials file holds the following values:

  • pipecd.url is the address of this instance's PipeCD web console, API and piped service.
  • pipecd.project is the PipeCD project to sign in to (SecureAnyCloud).
  • pipecd.admin.user and pipecd.admin.pass are the project's static administrator, for the web console.
  • pipecd.api.key is a READ_WRITE API key for pipectl and automation.
  • pipecd.piped.id is the ID of the on-box piped (its key is /etc/pipecd/piped/piped-key).
  • pipecd.demo.app.id is the ID of the demo application.
  • pipecd.mysql.user and pipecd.mysql.pass are the control plane's MySQL account, for backups.

To read the password and keys, run sudo cat /root/pipecd-credentials.txt in your own session, and then store them in your password manager.

3

Confirm PipeCD is running

Run the following commands to check the services. The first-boot unit has finished, Docker, the egress chain, the PipeCD stack and nginx are active, and exactly eight containers run.

The only public listening sockets are sshd and nginx on 22, 80 and 443. The control plane's gateway (9090) is on 127.0.0.1 only, and MySQL, the filestore and Valkey have no host port at all:

systemctl is-active pipecd-firstboot docker pipecd-egress pipecd nginx
sudo ss -Htlnp | awk '{print $4, $6}' | sed -E 's/,pid=[0-9]+,fd=[0-9]+//g' | sort -u sudo docker ps --format '{{.Names}} {{.Image}} {{.Ports}}' | sort
sudo cat /usr/share/pipecd/IMAGES
active active active active active 0.0.0.0:22 users:(("sshd"),("systemd")) 0.0.0.0:443 users:(("nginx"),("nginx"),("nginx")) 0.0.0.0:80 users:(("nginx"),("nginx"),("nginx")) 127.0.0.1:9090 users:(("docker-proxy")) 127.0.0.53%lo:53 users:(("systemd-resolve")) 127.0.0.54:53 users:(("systemd-resolve")) [::]:22 users:(("sshd"),("systemd")) [::]:443 users:(("nginx"),("nginx"),("nginx")) [::]:80 users:(("nginx"),("nginx"),("nginx")) pipecd-cache valkey/valkey 6379/tcp pipecd-gateway envoyproxy/envoy 127.0.0.1:9090->9090/tcp, 10000/tcp pipecd-mysql sac/pipecd-mysql:8.4.13 3306/tcp, 33060/tcp pipecd-ops sac/pipecd-controlplane:0.58.0 pipecd-piped sac/pipecd-piped:0.58.0 pipecd-piped-gw envoyproxy/envoy 10000/tcp pipecd-s3 sac/pipecd-s3:1.11.0 pipecd-server sac/pipecd-controlplane:0.58.0 controlplane sac/pipecd-controlplane:0.58.0 sha256:fc4700e7956f33e99d790793ba2e6209584414cb84d41e7535e1f81e8a9b5e56 (built from github.com/pipe-cd/pipecd v0.58.0, commit dc6a6a9a6f5b571985d77c192955d637de16970d, go1.26.10 linux/amd64; web UI static from the upstream controlplane image) piped sac/pipecd-piped:0.58.0 sha256:33cb925a6a439547ca971d8bd9a41b7f80f1fc134fb45dd81524a67aa2f1dcd4 (built from the same tree) mysql sac/pipecd-mysql:8.4.13 sha256:4465fa8bfe1fcac802825e38954094b2d0b94c5a58a6ab4f278f090fc9d050ed (derived from library/mysql 8.4.13: MySQL Shell and gosu removed, packages upgraded, USER mysql) s3 sac/pipecd-s3:1.11.0 sha256:5a55d938aae9fc6537dd820cd4aac82e5583969b0a4ebbe1c84b5baf694e89e0 (versitygw 1.11.0 release binary, sha256-verified, uid 10001) valkey valkey/valkey@sha256:ac81eb0a7b37e054000af8fdd5e6c3eb17249caa71eba79c003a145e518415e5 sha256:650ff8153447d257696648bc63a77522cf6e760145be45ce65a408a918229915 envoy envoyproxy/envoy@sha256:16e0d4dac937ffa34103aa6ba1013dc2030b9de2a249273c8d23c7c5c2989664 sha256:711883897f9d8a5cd5797f1ef41f49800f997291a8e9db812a8786c184466936 binary-sha256 fc370984050988d24e4045c97f49f4733abd2195000831e32869aaf2b6980c1c controlplane binary-sha256 42084285257cdb7730ba95a6c75754216b8d527c614e734a3dc57b2bd0b542fe piped source-sha256 d17c037e094473185a991e789b407793b45d3ace72f33304790f26e86e8cf119 go.mod source-sha256 9ee7b72b4d395167792f65cf2608c815d2fb6a670af2f3c4a579443ee7584e1b go.sum

The four sac/pipecd-* images were built on the image's build machine, from PipeCD's source and from the official MySQL and versitygw images. A locally built image has no registry digest, so /usr/share/pipecd/IMAGES records each one's image ID and what it was built from.

4

Prove the sign-in refusals and run the self-test

The web console's API refuses a visitor without a session. The API service and the piped service refuse a caller with no key or a wrong key. Plain HTTP redirects to HTTPS, an unknown Host header gets no answer, and TLS 1.1 is not offered.

The last command is the image's own round-trip check. It signs in as this instance's administrator over https://<your-name>/, and it refuses a wrong and an empty password first. It proves the anonymous and wrong-key refusals over gRPC-web and native gRPC, with this instance's own keys as the positive control. It also checks that the on-box piped is online and runs a real deployment of the demo application:

H=$(sudo sed -nE 's#^pipecd\.url=https://([^/]+)/?.*#\1#p' /root/pipecd-credentials.txt) printf '\x00\x00\x00\x00\x00' > /tmp/empty.grpc for s in webservice.WebService apiservice.APIService pipedservice.PipedService; do printf '%-28s %s\n' "$s" "$(curl -sk --http2 --connect-to ::127.0.0.1: -D - -o /dev/null -X POST \
  -H 'Content-Type: application/grpc' -H 'TE: trailers' --data-binary @/tmp/empty.grpc \
  "https://$H/grpc.service.$s/ListApplications" | tr -d '\r' | awk 'tolower($1)=="grpc-status:"{print "grpc-status", $2}')" done rm -f /tmp/empty.grpc curl -sk -o /dev/null -w '/login %{http_code}\n' --connect-to ::127.0.0.1: "https://$H/login" curl -s -D - -o /dev/null --connect-to ::127.0.0.1: "http://$H/" | grep -iE '^(HTTP|location)' curl -sk -o /dev/null -w 'unknown Host %{http_code}\n' -H 'Host: evil.example' https://127.0.0.1/ || true curl -sk -o /dev/null -w 'TLS 1.1 %{http_code}\n' --tls-max 1.1 --connect-to ::127.0.0.1: "https://$H/" || true
sudo pipecd-selftest
webservice.WebService grpc-status 16 apiservice.APIService grpc-status 16 pipedservice.PipedService grpc-status 16 /login 200 HTTP/1.1 301 Moved Permanently Location: https://ec2-203-0-113-25.compute-1.amazonaws.com/ unknown Host 000 TLS 1.1 000 PIPECD_SELFTEST_OK https://ec2-203-0-113-25.compute-1.amazonaws.com/ (pinned certificate): LOGIN_OK sign-in (wrong + empty password refused); web API anonymous Unauthenticated; API + piped services refuse no/wrong key, accept own key; piped ONLINE; malformed Cookie 400, well-formed 200; 80 -> 301; demo sync fa1224c5-8979-4a50-9e80-1e97dd65ddc3 SUCCESS with its stage marker

grpc-status 16 is gRPC's Unauthenticated. The --connect-to ::127.0.0.1: option sends each request to this instance while keeping the real host name in the request, exactly as a browser would send it. The value 000 means that the server closed the connection without an answer.

5

Sign in to the web console

Browse to pipecd.url (https://<public-dns-name>/). The certificate is self-signed, so your browser warns once. Accept it for this host, or install your own certificate (Step 8).

Enter the project name SecureAnyCloud and continue. Sign in with the user name admin and the pipecd.admin.pass value from the credentials file. The Login with GitHub and Login with OIDC buttons do nothing until you configure single sign-on for the project (Settings > Project), so use the user name and password form.

Then check the console:

  • Applications lists sac-demo, synced by the on-box piped.
  • Deployments shows the deployment that first boot ran. Open it to see its single SCRIPT_RUN stage and its log.
  • Settings > Piped shows the on-box piped sac-onbox-piped as online.
6

Deploy your own applications

piped finds an application's definition, app.pipecd.yaml, in a Git repository that it is configured to watch. The demo shows the shape. Its repository is /var/lib/pipecd/git/demo.git on the instance (piped sees it as file:///srv/git/demo.git, read-only), and its definition is /usr/share/pipecd/demo/demo/app.pipecd.yaml. The on-box piped's configuration is /etc/pipecd/piped/piped-config.yaml.

To deploy your own applications with the on-box piped:

  • Add your repository to repositories: in /etc/pipecd/piped/piped-config.yaml (an HTTPS URL, or SSH with a deploy key under git:). Add a platform provider for your target under platformProviders:, for example type: KUBERNETES with a kubeconfig, or type: ECS or type: LAMBDA with a region. Give the provider least-privilege credentials, and never an administrator role. Keep secrets in root-only files under /etc/pipecd/piped/ and refer to them by path.
  • Restart piped with sudo docker restart pipecd-piped.
  • In the web console, choose Applications > Add. Pick the piped, the repository and the path of the application's directory.

The on-box piped runs the deployments, so it can reach your VPC and the internet (see the Security posture).

To run piped somewhere else instead, for example inside your EKS cluster, register a new piped in Settings > Piped. The console shows its ID and key once. Point the new piped at this instance with apiAddress: <your-name>:443. The piped service is served by nginx on 443 with TLS, and the piped authenticates with its own per-piped key. Your off-box piped must trust this instance's certificate, so install a certificate from a CA that it trusts (Step 8) first. Allow 443 from the piped's address in the instance's security group.

pipectl, PipeCD's command-line client, talks to the API service on the same address with the API key: pipectl application list --address <your-name>:443 --api-key-file <file-with-the-key>. Add --cert-file <copy of /etc/ssl/pipecd/pipecd.crt> while the instance uses its self-signed certificate.

You can delete the demo application once you have your own. Choose Applications, open the demo application's menu, and choose Delete.

7

Check the security controls

The DOCKER-USER rules refuse the metadata addresses for every container and send traffic from the PipeCD networks to the egress chain. The following commands check each control:

  • From inside piped, instance metadata, the reserved ranges and this host are refused, while the public internet answers. The 200 is the positive control, and it shows that piped is not cut off: it can reach your VPC and the internet.
  • The control-plane server reaches nothing off its own network.
  • MySQL (3306), Valkey (6379) and the object store (7070) are closed on the host. Port 9090, the gateway that nginx proxies to on loopback only, is open, which is the positive control for that test.
  • The services carry IPAddressDeny.
  • SSH runs with the SecureAnyCloud pins.
sudo iptables -S DOCKER-USER
sudo ip6tables -S DOCKER-USER
sudo iptables -S SAC-PCD-EGRESS | grep -cE 'REJECT|DROP' for u in http://checkip.amazonaws.com/ http://169.254.169.254/latest/meta-data/ http://198.18.0.1/; do printf '%-42s piped %s\n' "$u" "$(sudo docker exec pipecd-piped curl -s -m 5 -o /dev/null -w '%{http_code}' "$u" || true)" done printf '%-42s server %s\n' http://checkip.amazonaws.com/ \
  "$(sudo docker exec pipecd-server wget -q -T 5 -O /dev/null http://checkip.amazonaws.com/ 2>/dev/null && echo reached || echo refused)" for p in 3306 6379 7070 9090; do if timeout 3 bash -c "exec 3<>/dev/tcp/127.0.0.1/$p" 2>/dev/null; then s=open; else s=closed; fi printf 'host -> 127.0.0.1:%s %s\n' "$p" "$s" done systemctl show -p IPAddressDeny docker pipecd nginx
sudo sshd -T | grep -E '^(passwordauthentication|permitrootlogin|kbdinteractiveauthentication|x11forwarding) '
-N DOCKER-USER -A DOCKER-USER -i br-pcd-+ -j SAC-PCD-EGRESS -A DOCKER-USER ! -i br-pcd-piped -o br-pcd-piped -m conntrack --ctstate NEW -j DROP -A DOCKER-USER ! -i br-pcd-pgw -o br-pcd-pgw -m conntrack --ctstate NEW -j DROP -A DOCKER-USER ! -i br-pcd-front -o br-pcd-front -m conntrack --ctstate NEW -j DROP -A DOCKER-USER ! -i br-pcd-cp -o br-pcd-cp -m conntrack --ctstate NEW -j DROP -A DOCKER-USER -d 168.63.129.16/32 -j REJECT --reject-with icmp-host-unreachable -A DOCKER-USER -d 169.254.169.254/32 -j REJECT --reject-with icmp-host-unreachable -N DOCKER-USER -A DOCKER-USER -i br-pcd-+ -j SAC-PCD-EGRESS -A DOCKER-USER -o br-pcd-+ -j DROP -A DOCKER-USER -d fd00:ec2::254/128 -j REJECT --reject-with icmp6-adm-prohibited 20 http://checkip.amazonaws.com/ piped 200 http://169.254.169.254/latest/meta-data/ piped 000 http://198.18.0.1/ piped 000 http://checkip.amazonaws.com/ server refused host -> 127.0.0.1:3306 closed host -> 127.0.0.1:6379 closed host -> 127.0.0.1:7070 closed host -> 127.0.0.1:9090 open IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128 IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128 IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128 permitrootlogin no passwordauthentication no kbdinteractiveauthentication no x11forwarding no
8

Serve PipeCD under your own DNS name

Point a DNS record (for example cd.example.com) at the instance's public or Elastic IP address, and then tell the image to serve that name. The command creates a new self-signed certificate for the name, pins nginx and the cross-site guard to it, updates pipecd.url in the credentials file and keeps the name across reboots:

sudo pipecd-set-hostname cd.example.com

For a trusted certificate, obtain one for that name, for example from your organization's CA or with certbot's certonly mode using its own temporary web server. Copy the certificate chain and key over /etc/ssl/pipecd/pipecd.crt and /etc/ssl/pipecd/pipecd.key (key mode 0600, root). Then run sudo systemctl reload nginx.

Maintenance

  • Change the admin password. PipeCD's static administrator is set in the control plane's configuration as a bcrypt hash. sudo pipecd-set-hostname does not change it. To rotate it, contact support or follow PipeCD's control-plane configuration docs, and then replace the old password in /root/pipecd-credentials.txt.
  • Add users. Connect an SSO provider (GitHub, Google or OIDC) and map its teams to PipeCD roles in Settings. Keep the static administrator for break-glass use.
  • Update the operating system. Unattended security upgrades are on. Reboot when /var/run/reboot-required exists. The metadata filter, the egress chain, the PipeCD stack and nginx start again by themselves.
  • Update PipeCD. The stack runs the images built for this image and never pulls one. To move to a newer release, launch the newer version of this image when the listing offers it, and move your data across with PipeCD stopped. Do not run docker image prune -a, because pipecd.service starts the shipped images only.
  • Back up. Snapshot the root volume. The control plane's data is in /var/lib/pipecd (MySQL in mysql/, the filestore's deployment logs and plans in s3/), and its secrets are in /etc/pipecd.
  • Read the logs. Run sudo docker logs pipecd-server for the control plane, sudo docker logs pipecd-piped for deployments and sudo docker logs pipecd-mysql for the datastore. Web requests are in /var/log/nginx/. Run sudo journalctl -u pipecd-firstboot for first boot.

Troubleshooting

  • The page does not load right after launch. First boot is still running. Run sudo journalctl -u pipecd-firstboot -f to follow its progress.
  • The browser shows "connection closed". nginx answers only the configured name and closes the connection for any other name. Use pipecd.url, or run sudo pipecd-set-hostname <name> for a new name.
  • Sign-in answers "429" or keeps failing. Sign-in is rate-limited per client IP address (per IPv4 address, or per single IPv6 address), not per account. Wait a minute after several failures, check that the project is SecureAnyCloud, and check the password in the credentials file.
  • A deployment cannot reach its target. Check the instance's outbound security-group rules, and then run sudo docker logs --tail 100 pipecd-piped. piped cannot reach instance metadata by design, so give it credentials for its platform providers explicitly.
  • "Failed to list released versions" appears on Settings > Piped. This is expected. The control plane has no route to the internet by design, so it cannot fetch PipeCD's release list from GitHub, and the Upgrade dialog offers no versions. Upgrade PipeCD by moving to a newer SecureAnyCloud image. The "Piped version v0.58.0 is available!" banner is PipeCD's own link to its release notes. Close it with its X.
  • piped shows offline. Run sudo docker logs --tail 50 pipecd-piped and sudo systemctl status pipecd.
  • 502 Bad Gateway. The control plane is starting or has stopped. Run sudo systemctl status pipecd and sudo docker logs --tail 50 pipecd-server to see why.
  • Run the end-to-end check. sudo pipecd-selftest signs in as this instance's administrator, runs a real deployment and prints PIPECD_SELFTEST_OK when everything works.

Licensing

PipeCD is licensed under the Apache License 2.0. Its license is on the instance in /usr/share/doc/pipecd/, together with the licenses of the Go modules compiled into its binaries.

MySQL Community Server is licensed under the GNU GPL version 2 with the Universal FOSS Exception. Valkey is licensed under the BSD 3-Clause license, and versitygw and Envoy are licensed under the Apache License 2.0. The MySQL and Valkey license texts and a notice for every component are in /usr/share/doc/pipecd/third-party/.

PipeCD is a Cloud Native Computing Foundation project. SecureAnyCloud is not affiliated with, sponsored by or endorsed by the PipeCD project or the CNCF, and the names identify the software that this image contains.

Support

SecureAnyCloud provides 24/7 technical support for this image by email and live chat. Support covers deployment, first login, HTTPS and DNS setup, piped configuration, deployment targets, off-box pipeds, storage, upgrades and troubleshooting. Contact sales@secureanycloud.com.

Deploy on AWS

Launch PipeCD 0.58.0 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.

View on Marketplace

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on AWS