GitLab CI integration
Automate deployments and server management with Alpacon in GitLab CI/CD pipelines using the official Docker container.
Quick start
1. Create a service token
CI and automation run on service tokens. A service token belongs to an application rather than to a person, so it survives staff changes, and its ACL bounds exactly what the pipeline may do.
- Go to IAM → applications and open the application this pipeline belongs to, or create one.
- Open the Tokens tab and click Create token.
- Name the token and set its expiry, choose its permissions from an access template or one by one, prepare its servers, commands, and paths, and on the review step write the reason it is needed.
- Copy or download the key when it is shown. It starts with
alpst-, and it is shown only once.
Before issuing the token, give the application a server account and a global role covering the required scopes. The examples use ci-deploy; replace it with that application-owned account. Prepare deployment directories and Docker access for this account. A service token cannot run as root or open an interactive Websh session.
On Alpacon Cloud, service-token sudo is allowed below Critical, including unassessed commands, and refused at Critical unless the workspace is Advisory. In Advisory, it is not refused for risk at any level, and the decision is recorded. Outside Advisory, a workspace token_exec rule can tighten the risk threshold. The workspace sudo setting must be on; otherwise sudo is refused with workspace_sudo_with_mfa_disabled. A default self-hosted installation refuses every service-token sudo attempt. The command rule must match the whole submitted line, including sudo. See Service tokens.
Command and file-transfer scopes always wait for approval in the web console. Have a Superuser or an approver for the request approve the token before adding ACLs or starting the pipeline.
2. Add the ACL rules
A new service token reaches nothing until you add ACL rules. Servers, commands, and file paths are each deny-by-default, so a token with no rules is refused everywhere.
After approval, open the token’s Access rules tab and apply the prepared rules, or add server and file rules there. On Alpacon Cloud, a Command ACL admins member adds commands under Pre-approved commands on the same tab. This access is separate from the workspace role. On self-hosted deployments, use command ACLs. Configure:
| Rule | What it bounds |
|---|---|
| Server ACL | Which servers the pipeline may reach |
| Command access | Which commands it may run, for example docker compose ... up -d |
| File ACL | Which paths it may upload to or download from |
A file transfer checks the server rule first, then the file rule. Skip the Access rules tab and the pipeline fails on its first command.
3. Add CI/CD variables
Add these variables to your GitLab project (Settings → CI/CD → Variables):
ALPACON_WORKSPACE: Your workspace name (e.g.,your-workspace)ALPACON_REGION: Your workspace region (us1orap1)ALPACON_SERVICE_TOKEN: Thealpst-key from step 1 (mark as Masked and Protected)DOCKER_USERNAME: Registry username for the Docker login example (mark as Masked)DOCKER_PASSWORD: Registry password for the Docker login example (mark as Masked)
The CLI reads the token from alpacon login only. There is no environment-variable auth path, so every job keeps that login step before the first Alpacon command.
4. Create .gitlab-ci.yml
IMPORTANT: The alpacax/alpacon-cli image has ENTRYPOINT ["alpacon"] set, so you must override it with entrypoint: [""] in GitLab CI.
stages:
- deploy
deploy:
stage: deploy
image:
name: alpacax/alpacon-cli:latest
entrypoint: [""]
script:
- alpacon login --workspace $ALPACON_WORKSPACE --region $ALPACON_REGION -t $ALPACON_SERVICE_TOKEN
- alpacon exec ci-deploy@prod-server "docker ps"
only:
- mainPrepare deployment directories
Before the first deployment, have a server administrator create /opt/myapp and give ownership to the application account (ci-deploy in these examples). Also prepare Docker access for that account. The pipeline uploads and deploys into this prepared directory.
Usage examples
Deploy with docker-compose.yml
deploy-compose:
stage: deploy
image:
name: alpacax/alpacon-cli:latest
entrypoint: [""]
script:
- alpacon login --workspace $ALPACON_WORKSPACE --region $ALPACON_REGION -t $ALPACON_SERVICE_TOKEN
- alpacon cp docker-compose.yml ci-deploy@prod-server:/opt/myapp/docker-compose.yml
- alpacon exec ci-deploy@prod-server "docker compose -f /opt/myapp/docker-compose.yml up -d"
- alpacon exec ci-deploy@prod-server "docker compose -f /opt/myapp/docker-compose.yml ps"
only:
- mainDeploy with environment file
Have an administrator prepare /opt/myapp with the application account as its owner before running this job. See Prepare deployment directories.
deploy-with-env:
stage: deploy
image:
name: alpacax/alpacon-cli:latest
entrypoint: [""]
script:
- alpacon login --workspace $ALPACON_WORKSPACE --region $ALPACON_REGION -t $ALPACON_SERVICE_TOKEN
# Upload files
- alpacon cp docker-compose.yml ci-deploy@prod-server:/opt/myapp/
- alpacon cp .env ci-deploy@prod-server:/opt/myapp/
# Deploy
- alpacon exec ci-deploy@prod-server "docker compose -f /opt/myapp/docker-compose.yml up -d"
- alpacon exec ci-deploy@prod-server "docker compose -f /opt/myapp/docker-compose.yml ps"
only:
- mainDeploy with image tag
deploy-tagged:
stage: deploy
image:
name: alpacax/alpacon-cli:latest
entrypoint: [""]
script:
- alpacon login --workspace $ALPACON_WORKSPACE --region $ALPACON_REGION -t $ALPACON_SERVICE_TOKEN
- alpacon exec --env="DOCKER_USERNAME" --env="DOCKER_PASSWORD" ci-deploy@prod-server 'printf "%s\n" "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin'
- alpacon cp docker-compose.yml ci-deploy@prod-server:/opt/myapp/docker-compose.yml
- alpacon exec --env="DOCKER_USERNAME" --env="IMAGE_TAG=$CI_COMMIT_SHORT_SHA" ci-deploy@prod-server "docker compose -f /opt/myapp/docker-compose.yml pull"
- alpacon exec --env="DOCKER_USERNAME" --env="IMAGE_TAG=$CI_COMMIT_SHORT_SHA" ci-deploy@prod-server "docker compose -f /opt/myapp/docker-compose.yml up -d"
- alpacon exec --env="DOCKER_USERNAME" --env="IMAGE_TAG=$CI_COMMIT_SHORT_SHA" ci-deploy@prod-server "docker compose -f /opt/myapp/docker-compose.yml ps"
only:
- mainMulti-environment deployment
Both jobs below use the same token, so its Server ACL has to list staging-server as well as prod-server. Issuing a token per environment instead, each scoped to its own server, keeps the staging pipeline from reaching production at all.
deploy-staging:
stage: deploy
image:
name: alpacax/alpacon-cli:latest
entrypoint: [""]
script:
- alpacon login --workspace $ALPACON_WORKSPACE --region $ALPACON_REGION -t $ALPACON_SERVICE_TOKEN
- alpacon cp docker-compose.yml ci-deploy@staging-server:/opt/myapp/docker-compose.yml
- alpacon exec ci-deploy@staging-server "docker compose -f /opt/myapp/docker-compose.yml up -d"
only:
- develop
environment:
name: staging
deploy-production:
stage: deploy
image:
name: alpacax/alpacon-cli:latest
entrypoint: [""]
script:
- alpacon login --workspace $ALPACON_WORKSPACE --region $ALPACON_REGION -t $ALPACON_SERVICE_TOKEN
- alpacon cp docker-compose.yml ci-deploy@prod-server:/opt/myapp/docker-compose.yml
- alpacon exec ci-deploy@prod-server "docker compose -f /opt/myapp/docker-compose.yml up -d"
only:
- main
environment:
name: production
when: manualComplete CI/CD pipeline
stages:
- build
- deploy
build-image:
stage: build
image: docker:latest
services:
- docker:dind
script:
- printf '%s\n' "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
- docker build -t $DOCKER_USERNAME/myapp:$CI_COMMIT_SHORT_SHA .
- docker push $DOCKER_USERNAME/myapp:$CI_COMMIT_SHORT_SHA
only:
- main
deploy:
stage: deploy
image:
name: alpacax/alpacon-cli:latest
entrypoint: [""]
script:
- alpacon login --workspace $ALPACON_WORKSPACE --region $ALPACON_REGION -t $ALPACON_SERVICE_TOKEN
- alpacon exec --env="DOCKER_USERNAME" --env="DOCKER_PASSWORD" ci-deploy@prod-server 'printf "%s\n" "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin'
- alpacon cp docker-compose.yml ci-deploy@prod-server:/opt/myapp/docker-compose.yml
- alpacon exec --env="DOCKER_USERNAME" --env="IMAGE_TAG=$CI_COMMIT_SHORT_SHA" ci-deploy@prod-server "docker compose -f /opt/myapp/docker-compose.yml pull"
- alpacon exec --env="DOCKER_USERNAME" --env="IMAGE_TAG=$CI_COMMIT_SHORT_SHA" ci-deploy@prod-server "docker compose -f /opt/myapp/docker-compose.yml up -d"
- alpacon exec --env="DOCKER_USERNAME" --env="IMAGE_TAG=$CI_COMMIT_SHORT_SHA" ci-deploy@prod-server "docker compose -f /opt/myapp/docker-compose.yml ps"
only:
- main
needs:
- build-imageSecurity
All commands executed through Alpacon are recorded in the workspace audit log, attributed to the application that owns the token rather than to a person. Sensitive values (such as passwords and tokens) passed via --env are automatically masked in command history.
Troubleshooting
Entrypoint error
Symptom: Error: unknown command "sh" for "alpacon"
Solution:
You forgot to add entrypoint: [""] to the image configuration. Use:
image:
name: alpacax/alpacon-cli:latest
entrypoint: [""]Login fails on a valid service token
Symptom: alpacon login reports failed to verify user profile, even though the alpst- key was copied correctly
Solution:
Service tokens need Alpacon CLI v1.7.4 or later. An older CLI doesn’t recognize the alpst- key and reports this misleading message instead. Check the version the job actually runs—a self-hosted runner or a pinned alpacax/alpacon-cli image tag is the usual cause—and upgrade it.
Command or file refused
Symptom: A command or alpacon cp that works from your own terminal is refused in the pipeline
Solution: Check the token’s server and file ACLs and the account the command runs as. On Cloud, ask a Command ACL admin to review the token’s pre-approved commands; on self-hosted deployments, check its command ACL. See Automation failure modes.
Permission denied
Symptom: permission denied when running Docker commands
Solution:
Use the application’s account: alpacon exec ci-deploy@server-name "docker ps". Check that this account has the required host permissions. A service token cannot run as root; widening an ACL does not change that.
File not found after upload
Symptom: File uploaded successfully but not found when executing commands
Solution: Have the server administrator prepare the parent directory for the application’s account. Then create the subdirectory and upload with that account:
- alpacon exec ci-deploy@server "mkdir -p /path/to/dir"
- alpacon cp file.txt ci-deploy@server:/path/to/dir/