Deployment¶
This guide covers deploying PikoCI on a single server. This setup uses in-memory pubsub and an embedded worker, which is suitable for demos and small teams.
For production scaling with multiple workers or high availability, use an external queue backend and run workers separately. See Queue Backends and Running Workers Separately.
Quick start¶
Download or build the binary and run it:
PikoCI is now running on port 8080. That's it for a minimal deploy.
Production single-server setup¶
This setup runs PikoCI as a bare binary managed by systemd, with supporting services (Caddy, Prometheus, Grafana, Node Exporter) in Docker Compose. This avoids Docker-in-Docker while keeping infrastructure containerized.
All config files are in the deploy/ directory.
1. Install PikoCI¶
Copy the binary to the server:
# Build from source
GOOS=linux GOARCH=amd64 go build -o pikoci .
scp pikoci root@your-server:/usr/local/bin/pikoci
# Or download a release
curl -L https://github.com/xescugc/pikoci/releases/latest/download/linux-amd64 -o /usr/local/bin/pikoci
chmod +x /usr/local/bin/pikoci
Alternatively, use the Docker image:
docker pull xescugc/pikoci:latest
docker run -p 8080:8080 xescugc/pikoci:latest server --db-system mem --pubsub-system mem --jwt-secret my-secret --run-worker
The image is based on Alpine and includes git, jq, curl, openssl, and docker-cli. See the Dockerfile for details.
2. Install prerequisites¶
The server needs git, jq, and curl for the built-in resource types (e.g. the git resource type uses jq and curl to query GitHub/GitLab APIs). Docker is required for the docker runner and for supporting services.
The deploy script (deploy/deploy.sh) installs these automatically if missing.
3. Create the system user and directories¶
useradd --system --no-create-home pikoci
mkdir -p /var/lib/pikoci /etc/pikoci
chown pikoci:pikoci /var/lib/pikoci
4. Configure PikoCI¶
Copy the example env file and fill in your values:
Edit deploy/pikoci.env with your secrets:
JWT_SECRET=your-secure-random-secret
DB_SYSTEM=sqlite
DB_NAME=/var/lib/pikoci/pikoci.db
PUBSUB_SYSTEM=mem
RUN_WORKER=true
GF_SECURITY_ADMIN_PASSWORD=your-grafana-password
Override the default admin password:
pikoci user-password -u admin -p your-password
# Add the output to deploy/pikoci.env as:
# USERS=admin:$2a$10$...
deploy/pikoci.env is gitignored — only the .example file is tracked.
See Server Configuration for all available options.
5. Deploy¶
The deploy script copies everything to the server — binary, configs, and env files:
Or deploy manually:
# Install systemd unit
cp deploy/pikoci.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable --now pikoci
Verify it's running:
6. Supporting services¶
The deploy script also syncs Docker Compose configs and env files. To start them manually:
This starts:
- Caddy — reverse proxy with automatic HTTPS (ports 80/443)
- Prometheus — scrapes PikoCI
/metricsand Node Exporter - Grafana — dashboards (accessible at
grafana.pikoci.com) - Node Exporter — host-level metrics
7. DNS¶
Point your domain's A record to the server IP:
pikoci.com(or your domain) → server IPgrafana.pikoci.com→ server IP
Caddy handles TLS certificates automatically via Let's Encrypt.
Secrets management¶
- Keep your secrets in
deploy/pikoci.envlocally (gitignored). The deploy script copies it to the server with correct permissions (chmod 600) - The
pikoci.env.examplefile is a template — never commit actual secrets - Generate JWT secrets with:
openssl rand -hex 32 - Generate password hashes with:
pikoci user-password -u <user> -p <password> - For standalone workers, generate a worker token with
pikoci worker-token --jwt-secret <secret>instead of distributing the raw JWT secret. See Running Workers Separately
Monitoring¶
PikoCI exposes a /metrics endpoint in Prometheus format with:
- Go runtime metrics (goroutines, memory, GC)
- HTTP request counts by status code and method
- HTTP request duration histograms
The included prometheus.yml scrapes both PikoCI and Node Exporter. Add Prometheus as a data source in Grafana to build dashboards.
Deploy script¶
The deploy/deploy.sh script automates the deploy process:
# Download latest release from GitHub and deploy
./deploy/deploy.sh root@your-server
# Or build from source instead
./deploy/deploy.sh --build root@your-server
It downloads the binary (or builds it with --build), copies it and all configs (including the env file) to the server, restarts the systemd service, and runs docker compose up -d.
Self-deploy pipeline¶
PikoCI can deploy itself using graceful shutdown. The included deploy/pipeline.hcl has a deploy job that:
- Waits for the
build-latestDocker image job to pass - Builds a new binary from master
- Copies it to
/usr/local/bin/pikoci - Sends
SIGQUITto the running process
SIGQUIT triggers a graceful shutdown: PikoCI finishes the deploy job itself, then exits cleanly. Because the systemd unit uses Restart=always, systemd automatically restarts PikoCI with the new binary.
job "deploy" {
get "git" "pikoci_master" {
trigger = true
passed = ["build-latest"]
}
task "deploy" {
run "exec" {
path = "/bin/sh"
args = [
"-ec",
<<-EOT
cd ${var.git_name}
GOOS=linux GOARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') go build -o /tmp/pikoci-new .
sudo cp /tmp/pikoci-new /usr/local/bin/pikoci
sudo kill -QUIT $(pidof pikoci)
EOT
]
}
}
}
See Server Configuration — Signal handling for details on SIGQUIT vs SIGTERM behavior.