Skip to main content
Version: Enterprise Edition v1.5 (latest)

Single Linux Machine

This page explains how to install the Semaphore Enterprise Edition control plane on a single Linux Server.

Overview

If this is your first time using Semaphore, we suggest trying out Semaphore Cloud to see if the platform fits your needs. You can create a free trial account without a credit card and use every feature.

The self-hosted installation is recommended for users and teams that are already familiar with Semaphore.

Prerequisites

  • A license
  • A domain
  • A Linux machine running Ubuntu. Preferably Ubuntu 24.04 LTS
    • Minimum memory: 16GB RAM
    • Minimum compute: 8 CPUs
  • A public IP address.
  • External access requires ports SSH (22), HTTP (80), and HTTPS (443) to be open
  • SSH access to the machine
  • Sudo or root access in the machine
note

Ensure that your VMs are running with hardware-supported virtualization mode enabled. Without this feature, Semaphore might not run at all, even when the minimum hardware requirements are met.

Step 1 - Obtain a License

The Enterprise Edition of Semaphore requires a license to operate. Depending on your company size, you may qualify for a free license.

To obtain a license and learn more, see the how to obtain a license page.

Step 2 - Define the domain

We highly recommend installing Semaphore on a subdomain. Installing Semaphore on your base domain might interfere with other services running on the same domain.

If your base domain is example.com, you should define a subdomain such as ci.example.com for your Semaphore installation.

Step 3 - Prepare the machine

  1. Copy the license file to the VM

    Copy license file to VM
    scp path/to/license-file <user>@<hostname>:/tmp
  2. Open a terminal on your Linux machine, e.g., using SSH

    Connect to your machine
    ssh <user>@<hostname>
  3. Create a user to run Semaphore and give them sudo powers

    Remote shell: create semaphore user with sudo
    sudo adduser semaphore
    sudo usermod -aG sudo semaphore
    su - semaphore
  4. Create a folder to store the config files

    Remote shell: Create install folder
    mkdir semaphore-install
    cd semaphore-install
  5. Create a file with the following environment variables

    • DOMAIN: subdomain + domain for your installation
    • LICENSE_FILE: license file name
    • IP_ADDRESS: public IP address of the machine
    • ROOT_EMAIL: email for the owner/administrator of the Semaphore server
    • ROOT_NAME: Name for the owner/administrator of the Semaphore server

    Remote shell: create semaphore-config file (example)
    echo export DOMAIN="ci.example.com" > semaphore-config
    echo export LICENSE_FILE="license-file-name.txt" >> semaphore-config
    echo export IP_ADDRESS="1.2.3.4" >> semaphore-config
    echo export ROOT_EMAIL="admin@example.com" >> semaphore-config
    echo export ROOT_NAME=\"Semaphore admin\" >> semaphore-config
  6. Move the license file to the installation directory

    Remote shell: move license file
    source semaphore-config
    sudo mv /tmp/${LICENSE_FILE} .
    sudo chown semaphore:semaphore $LICENSE_FILE
  7. Install certbot

    remote shell: install certbot
    sudo apt-get update
    sudo apt-get -y install certbot

Step 4 - Create DNS A Records

Configure your DNS by creating two A records that point to the server IP address.

  1. Go to your domain provider's DNS settings

  2. Create A record for your subdomain

    • Type: A
    • Name: your subdomain + domain (e.g. ci.example.com)
    • Value: the public IP address of your Linux machine
  3. Create a wildcard record

    • Type: A
    • Name: your subdomain + domain (e.g. *.ci.example.com)
    • Value: the public IP address of your Linux machine
  4. Wait for DNS propagation (typically a few minutes)

    You can verify the creation of the A record in the Online Dig Tool for:

    • ci.example.com
    • id.ci.example.com

Step 5 - Create TLS certificates

You must create a wildcard TLS certificate for your Semaphore subdomain, e.g., ci.example.com. Note that this certificate expires three months after generation.

Certificates are not auto-renewed. Once expired, you must execute this step again to generate new certificates and then re-run Helm upgrade with the same argument.

  1. Still logged in your VM, install certbot in the Linux server

    Remote shell: install certbot
    sudo apt-get update
    sudo apt-get -y install certbot
  2. Run certbot to create a TLS certificate

    Remote shell: create certificates with certbot
    source semaphore-config
    mkdir -p certs
    certbot certonly --manual --preferred-challenges=dns \
    -d "*.${DOMAIN}" \
    --register-unsafely-without-email \
    --work-dir certs \
    --config-dir certs \
    --logs-dir certs
  3. You are prompted to create a DNS TXT record to verify ownership of the domain

    Remote shell: certbot challenge message
    Please deploy a DNS TXT record under the name:

    _acme-challenge.ci.example.com.

    with the following value:

    EL545Zty7vUUvIHQRSkwxXTWsirldw91enasgB5uOHs
  4. Go to your domain's console and create the DNS TXT record required by certbot. Wait for the record to be propagated

    tip

    You can verify the creation of the TXT record in the Google Dig Tool. Type the challenge DNS TXT record and check if its value corresponds to the correct value.

  5. Continue the certbot process. You should see a message like this

    Remote shell: certificate generated message
    Successfully received the certificate.
    Certificate is saved at: certs/live/ci.example.com/fullchain.pem
    Key is saved at: certs/live/ci.example.com/privkey.pem
    This certificate expires on 2025-02-27.
    These files will be updated when the certificate renews.
  6. Check the existence of the certificate files on the following paths. You will require both files during the Semaphore installation.

    • Full chain certificate: ./certs/live/$DOMAIN/fullchain.pem
    • Private key certificate: ./certs/live/$DOMAIN/privkey.pem
  7. You may delete the DNS TXT record from your domain at this point. It's no longer needed.

Step 6 - Install K3s and CRDs

In this step, we install and configure K3s to run Semaphore.

  1. Still inside the remote shell in your Linux machine, install Helm with:

    Remote shell: install Helm
    curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
    chmod 700 get_helm.sh
    sudo ./get_helm.sh
  2. Install K3s

    Remote shell: install k3s
    curl -sfL https://get.k3s.io | sudo K3S_KUBECONFIG_MODE="644" sh -
  3. Add KUBECONFIG to your shell environment

    Remote shell: set KUBECONFIG in your bashrc
    echo export KUBECONFIG=/etc/rancher/k3s/k3s.yaml >> ~/.bashrc
    source ~/.bashrc
  4. Optionally, install k9s to manage and observe your K3s system

    wget https://github.com/derailed/k9s/releases/latest/download/k9s_linux_amd64.deb && sudo apt install ./k9s_linux_amd64.deb && rm k9s_linux_amd64.deb
  5. Install Emissary Ingress Controller

    Remote shell: install Emissary CRD
    kubectl apply -f https://app.getambassador.io/yaml/emissary/3.9.1/emissary-crds.yaml
    kubectl wait --timeout=90s --for=condition=available deployment emissary-apiext -n emissary-system

Step 7 - Install Semaphore

note

This step installs the Enterprise Edition. If you want to install the Community Edition, see the Community Installation page.

  1. Sanity check your environment before installing Semaphore. These commands should return valid values

    Remote shell: check if ready to install
    source semaphore-config
    echo "DOMAIN=${DOMAIN}"
    echo "IP_ADDRESS=${IP_ADDRESS}"
    ls certs/live/${DOMAIN}/fullchain.pem certs/live/${DOMAIN}/privkey.pem $LICENSE_FILE
  2. Install Semaphore with Helm. The installation usually takes between 10 and 30 minutes

    Remote shell: install Semaphore
    helm upgrade --install semaphore "oci://ghcr.io/semaphoreio/semaphore" \
    --debug \
    --version v1.5.0 \
    --timeout 30m \
    --set global.edition=ee \
    --set global.license="$(cat ${LICENSE_FILE})"\
    --set global.rootUser.email="${ROOT_EMAIL}" \
    --set global.rootUser.name="${ROOT_NAME}" \
    --set global.domain.ip="${IP_ADDRESS}" \
    --set global.domain.name="${DOMAIN}" \
    --set ingress.enabled=true \
    --set ingress.ssl.enabled=true \
    --set ingress.className=traefik \
    --set ingress.ssl.type=custom \
    --set ingress.ssl.crt="$(cat certs/live/${DOMAIN}/fullchain.pem | base64 -w 0)" \
    --set ingress.ssl.key="$(cat certs/live/${DOMAIN}/privkey.pem | base64 -w 0)"
  3. Once installed, you should see this message

    Remote shell: installation complete message
    =============================================================================================
    Congratulations, Semaphore has been installed successfully!

    To start using the app, go to: https://id.ci.tomfern.com/login

    You can fetch credentials for the login running this command:

    echo "Email: $(kubectl get secret semaphore-authentication -n default -o jsonpath='{.data.ROOT_USER_EMAIL}' | base64 -d)"; echo "Password: $(kubectl get secret semaphore-authentication -n default -o jsonpath='{.data.ROOT_USER_PASSWORD}' | base64 -d)"; echo "API Token: $(kubectl get secret semaphore-authentication -n default -o jsonpath='{.data.ROOT_USER_TOKEN}' | base64 -d)"
    =============================================================================================
  4. Execute the shown command to retrieve the login credentials.

    Remote shell: get login credentials
    echo "Email: $(kubectl get secret semaphore-authentication -n default -o jsonpath='{.data.ROOT_USER_EMAIL}' | base64 -d)"; echo "Password: $(kubectl get secret semaphore-authentication -n default -o jsonpath='{.data.ROOT_USER_PASSWORD}' | base64 -d)"; echo "API Token: $(kubectl get secret semaphore-authentication -n default -o jsonpath='{.data.ROOT_USER_TOKEN}' | base64 -d)"

    Email: root@example.com
    Password: AhGg_2v6uHuy7hqvNmeLw0O4RqI=
    API Token: nQjnaPKQvW6TqXtpTNSx
  5. Backup your semaphore-config file in a safe place. It is required to upgrade Semaphore, update your license, and renew expired certificates

  6. On your browser, open the subdomain where Semaphore was installed prefixed with id, e.g., id.ci.example.com

  7. Fill in the username and password. You might be prompted to set a new password

    Log in screen for Semaphore

  8. Open the server menu and select Settings

    Server settings menu

  9. Select Initialization jobs

    Init job configuration

  10. Select the Environment Type to Self-hosted Machine

  11. Select Machine Type to s1-kubernetes and press Save changes

    note

    You should press Save changes even if the options were already selected.

  12. Return to the Semaphore initial page. On the Learn tab, you'll find the onboarding guide. Follow it to complete the setup and build your first project

    Onboarding guide screen

See also