Skip to main content
Version: 25.1

SSL/TLS

HTTP must not be used in production environments. An SSL certificate is required for your Seqera instance to handle HTTPS traffic. Private certificates are supported, but require additional configuration during Seqera Enterprise installation and Nextflow execution.

AWS deployments: Manage SSL certificates with Amazon Certificate Manager (ACM)

Use Amazon Certificate Manager (ACM) to apply SSL certificates to your AWS deployment:

Configure Seqera to trust your private certificate

If you secure related infrastructure (such as private Git repositories) with certificates issued by a private Certificate Authority, these certificates must be loaded into the Seqera Enterprise containers. You can achieve this in several ways.

Configure private certificate trust

  1. This guide assumes you're using the original containers supplied by Seqera.
  2. Replace TARGET_HOSTNAME, TARGET_ALIAS, and PRIVATE_CERT.pem with your unique values.
  3. Previous instructions advised using openssl. The native keytool utility is preferred as it simplifies steps and better accommodates private CA certificates.

Use Docker volume

  1. Retrieve the private certificate on your Seqera container host:

    keytool -printcert -rfc -sslserver TARGET_HOSTNAME:443  >  /PRIVATE_CERT.pem
  2. Modify the backend and cron container configuration blocks in docker-compose.yml:

    CONTAINER_NAME:
    # -- Other keys here like `image` and `networks`--

    # Add a new mount for the downloaded certificate
    volumes:
    - type: bind
    source: /PRIVATE_CERT.pem
    target: /etc/pki/ca-trust/source/anchors/PRIVATE_CERT.pem

    # Add a new keytool import line PRIOR to 'update-ca-trust' for the certificate
    command: >
    sh -c "keytool -import -trustcacerts -storepass changeit -noprompt -alias TARGET_ALIAS -file /etc/pki/ca-trust/source/anchor/TARGET_HOSTNAME.pem &&
    update-ca-trust &&
    /wait-for-it.sh db:3306 -t 60 &&
    /tower.sh"
caution

The two Kubernetes procedures that follow import the certificate directly into the JVM trust store inside the container image. This requires a writable container root filesystem. If you deploy with the Seqera Helm charts, follow Use Helm charts instead.

Use K8s ConfigMap

  1. Retrieve the private certificate on a machine with CLI access to your Kubernetes cluster:

    keytool -printcert -rfc -sslserver TARGET_HOSTNAME:443 > /PRIVATE_CERT.pem
  2. Load the certificate as a ConfigMap in the same namespace where your Seqera instance will run:

    kubectl create configmap private-cert-pemstore --from-file=/PRIVATE_CERT.pem
  3. Modify both the backend and cron Deployment objects:

    • Define a new volume based on the certificate ConfigMap:

      spec:
      template:
      spec:
      volumes:
      - name: private-cert-pemstore
      configMap:
      name: private-cert-pemstore
    • Add a volumeMount entry into the container definition:

      spec:
      template:
      spec:
      containers:
      - name: CONTAINER_NAME
      volumeMounts:
      - name: private-cert-pemstore
      mountPath: /etc/pki/ca-trust/source/anchors/PRIVATE_CERT.pem
      subPath: PRIVATE_CERT.pem
    • Modify the container start command to load the certificate prior to running your Seqera instance:

      spec:
      template:
      spec:
      containers:
      - name: CONTAINER_NAME
      command: ["/bin/sh"]
      args:
      - -c
      - |
      keytool -import -trustcacerts -cacerts -storepass changeit -noprompt -alias TARGET_ALIAS -file /etc/pki/ca-trust/source/anchors/PRIVATE_CERT.pem;
      ./tower.sh

Download on Pod start

  1. Modify both the backend and cron Deployment objects to retrieve and load the certificate prior to running your Seqera instance:

    spec:
    template:
    spec:
    containers:
    - name: CONTAINER_NAME
    command: ["/bin/sh"]
    args:
    - -c
    - |
    keytool -printcert -rfc -sslserver TARGET_HOST:443 > /PRIVATE_CERT.pem;
    keytool -import -trustcacerts -cacerts -storepass changeit -noprompt -alias TARGET_ALIAS -file /PRIVATE_CERT.pem;
    ./tower.sh

Use Helm charts

The Seqera Helm charts set containerSecurityContext.readOnlyRootFilesystem: true by default for every component except Studios. Because the root filesystem is read-only, an in-place import into the image's trust store fails when the pod starts:

keytool error: java.io.FileNotFoundException: /usr/lib/jvm/JDK_VERSION/lib/security/cacerts (Read-only file system)

keytool prints Certificate was added to keystore before it writes the keystore back to disk. The error appears immediately after this apparent success message. Treat the error, not the success line, as the outcome.

Mounted volumes remain writable when readOnlyRootFilesystem is enabled. Copy the trust store to a volume, import your certificate into the copy, then point the JVM at the copy.

  1. Load the certificate as a ConfigMap in the same namespace as your release:

    kubectl create configmap private-cert-pemstore --from-file=/PRIVATE_CERT.pem
  2. Add the following to your values file. This example configures Wave. The same command, args, extraVolumes, extraVolumeMounts, and extraEnvVars keys are available for backend, cron, and the other components. Studios takes them under studios.proxy and studios.server:

    wave:
    command: ["/bin/sh"]
    args:
    - -c
    - |
    cp $JAVA_HOME/lib/security/cacerts /opt/cacerts/cacerts
    chmod +w /opt/cacerts/cacerts
    keytool -import -trustcacerts -storepass changeit -noprompt -alias TARGET_ALIAS -file /ca/PRIVATE_CERT.pem -keystore /opt/cacerts/cacerts
    /launch.sh
    extraVolumes:
    - name: cacerts
    emptyDir: {}
    - name: private-cert-pemstore
    configMap:
    name: private-cert-pemstore
    extraVolumeMounts:
    - name: cacerts
    mountPath: /opt/cacerts
    - name: private-cert-pemstore
    mountPath: /ca/PRIVATE_CERT.pem
    subPath: PRIVATE_CERT.pem
    extraEnvVars:
    - name: JAVA_TOOL_OPTIONS
    value: "-Djavax.net.ssl.trustStore=/opt/cacerts/cacerts"

    Replace /launch.sh with ./tower.sh for the backend and cron components. To avoid overriding the container command, copy and import the certificate in an initContainers entry that mounts the same cacerts volume.

  3. Confirm that the JVM received the flag. The pod log prints the following line at startup:

    Picked up JAVA_TOOL_OPTIONS: -Djavax.net.ssl.trustStore=/opt/cacerts/cacerts

    If the line is absent, the JVM never received the flag and your trust store has no effect. Check the rendered environment with kubectl get deploy DEPLOYMENT_NAME -o jsonpath='{.spec.template.spec.containers[0].env}'. A frequent cause is an extraEnvVars entry that is not a list of name and value maps. Because - MY_VAR: "some-value" has no name key, the charts render it as name: <nil> with no value and the variable you intended is never set.

note

Use JAVA_TOOL_OPTIONS rather than a component-specific variable. Because the JVM reads JAVA_TOOL_OPTIONS directly, it works for every Seqera Java service. JAVA_TOOL_OPTIONS also adds your flag without replacing the JVM options that each container sets by default. The backend and cron containers read JAVA_OPTS, but Wave ignores it and reads WAVE_JVM_OPTS instead. Setting WAVE_JVM_OPTS replaces the default Wave heap, garbage collector, and Netty options rather than adding to them.

note

Copying the full trust store before importing keeps the public Certificate Authorities trusted and leaves other outbound connections unaffected. If PRIVATE_CERT.pem holds a chain of more than one certificate, keytool -import adds only the first. Import each certificate under its own alias, or import only the root Certificate Authority that anchors the chain.

Configure the Nextflow launcher image to trust your private certificate

If you secure infrastructure such as private Git repositories or your Seqera Enterprise instance with certificates issued by a private Certificate Authority, these certificates must also be loaded into the Nextflow launcher container.

Import private certificates via pre-run script

  1. This configuration assumes you're using the default nf-launcher image supplied by Seqera.
  2. Replace TARGET_HOSTNAME, TARGET_ALIAS, and PRIVATE_CERT.pem with your unique values.
  3. Previous instructions advised using openssl. The native keytool utility is preferred as it simplifies steps and better accommodates private CA certificates.

Add the following to your compute environment pre-run script:

keytool -printcert -rfc -sslserver TARGET_HOSTNAME:443  >  /PRIVATE_CERT.pem
keytool -import -trustcacerts -cacerts -storepass changeit -noprompt -alias TARGET_ALIAS -file /PRIVATE_CERT.pem

cp /PRIVATE_CERT.pem /etc/pki/ca-trust/source/anchors/PRIVATE_CERT.pem
update-ca-trust

Configure Seqera to present a SSL/TLS certificate

You can secure your Seqera instance with a TLS certificate in several ways.

Place a load balancer, configured to present a certificate and act as a TLS termination point, in front of your Seqera instance.

This solution is likely already implemented for cloud-based Kubernetes implementations and can be easily implemented for Docker Compose-based stacks. See this example.

Reverse proxy container

This solution works well for Docker Compose-based stacks to avoid the additional cost and maintenance of a load balancer. See this example.

Modify frontend container

Due to complications that can be encountered during upgrades, this approach is not recommended.

Show me anyway

This example assumes deployment on an Amazon Linux 2 AMI.

  1. Install NGINX and other required packages:

    sudo amazon-linux-extras install nginx1.12
    sudo wget -r --no-parent -A 'epel-release-*.rpm' https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/
    sudo rpm -Uvh dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-*.rpm
    sudo yum-config-manager --enable epel*
    sudo yum repolist all
    sudo amazon-linux-extras install epel -y
  2. Generate a private certificate and key.

  3. Make a local copy of the /etc/nginx/templates/tower.conf.template file from the frontend container, or create a ConfigMap to store it if you're using Kubernetes.

  4. Replace the listen directives in the server block with the following:

    listen ${NGINX_LISTEN_PORT} ssl default_server;
    listen [::]:${NGINX_LISTEN_PORT_IPV6} ssl default_server;

    ssl_certificate /etc/ssl/testcrt.crt;
    ssl_certificate_key /etc/ssl/testkey.key;
  5. Modify the frontend container definition in your docker-compose.yml file or Kubernetes manifest:

    frontend:
    image: cr.seqera.io/frontend:${TAG}
    networks:
    - frontend
    environment:
    NGINX_LISTEN_PORT: 8081
    NGINX_LISTEN_PORT_IPV6: 8443
    ports:
    - 8000:8081
    - 443:8443
    volumes:
    - $PWD/tower.conf.template:/etc/nginx/templates/tower.conf.template
    - $PWD/cert/testcrt.crt:/etc/ssl/testcrt.crt
    - $PWD/cert/testkey.key:/etc/ssl/testkey.key
    restart: always
    depends_on:
    - backend

TLS version support

Seqera Enterprise versions 22.3.2 and earlier rely on Java 11 (Amazon Corretto). You may encounter issues when integrating with third-party services that enforce TLS v1.2 (such as Azure Active Directory OIDC).

TLS v1.2 can be explicitly enabled by default using JDK environment variables:

_JAVA_OPTS="-Dmail.smtp.ssl.protocols=TLSv1.2"