Published on: September 2, 2025

16 min read

Secure Rust development with GitLab

Learn how GitLab supports Rust development through its CI/CD capabilities, security scanning, dedicated Rust integrations, AI features, and more.

Rust has emerged as one of the most beloved programming languages due to its performance, memory safety, and concurrency features. As Rust adoption continues to grow, many developers are looking for robust CI/CD platforms to support their Rust projects.

GitLab's appeal to Rust developers extends beyond simple code hosting. The platform offers robust CI/CD capabilities that align perfectly with Rust's emphasis on safety, performance, and reliability. GitLab makes it easy to create repositories and use off-the-shelf Docker containers to put together custom CI jobs. Developers can easily set up automated testing, cross-platform builds, and documentation generation. The platform's integrated approach to DevSecOps resonates with Rust's philosophy of providing comprehensive tooling out of the box.

About the demo application

Being interested in how mortgage rates affect monthly payments and how hard it is to to afford a house in the current times, I decided to write a mortgage calculator in Rust, which I will use as an example throughout this tutorial. Feel free to import this project and follow along.

The mortgage calculator will help users calculate monthly mortgage payments, including principal, interest, property taxes, insurance, PMI, and HOA fees. It provides a modern, intuitive GUI using the egui framework, as well as a CLI for running it in the terminal.

Mortgage calculator GUI

This application contains a .gitlab-ci.yml that generates a pipeline, which will build, test, package, scan, and deploy the software. We will go over this pipeline definition in detail in the sections below.

Mortgage Calculator Pipeline

Building and testing Rust applications

GitLab's Docker-based CI/CD system excels at Rust development workflows, providing a robust foundation for compilation, testing, and code quality checks. The platform's caching mechanisms are particularly valuable for Rust projects, which can have lengthy compilation times due to the language's thorough optimization and safety checking processes.

Building

Rust's excellent cross-compilation capabilities combined with GitLab's flexible CI/CD system create a powerful solution for building applications across multiple platforms. This is particularly valuable for Rust applications that need to run on various operating systems and architectures without sacrificing performance or requiring platform-specific code.

Note: You can learn more about the .gitlab-ci.yml by reading the CI/CD YAML syntax reference.

# Cache configuration to speed up builds by reusing dependencies
cache:
  key: $CI_COMMIT_REF_SLUG                               # Use branch name as cache key
  paths:
    - .cargo/                                            # Cache Cargo registry and git dependencies
    - target/                                            # Cache compiled artifacts

# Base template for Rust jobs - shared configuration
.rust-template:
  image: rust:$RUST_VERSION-slim                         # Use slim Rust image for faster downloads
  before_script:
    # Install system dependencies required for building the Rust application
    - apt-get update && apt-get install -y pkg-config libssl-dev libgtk-3-dev libxcb-shape0-dev libxcb-xfixes0-dev

# Template for cross-compilation build jobs
.build-template:
  extends: .rust-template                                # Inherit from rust-template
  stage: build                                           # Execute during build stage
  script:
    - rustup target add $TARGET                          # Add the target platform for cross-compilation
    - cargo build --release --target $TARGET             # Build optimized release binary for target platform

# Build for Linux x86_64 (primary target platform)
build-linux:
  extends: .build-template                               # Use build template configuration
  variables:
    TARGET: x86_64-unknown-linux-gnu                     # Linux 64-bit target
  artifacts:
    paths:
      - target/$TARGET/release/mortgage-calculator       # Save the compiled binary
    expire_in: 1 week                                    # Keep artifacts for 1 week
  allow_failure: false                                   # This build must succeed

# Build for Windows x86_64 (cross-compilation)
build-windows:
  extends: .build-template                               # Use build template configuration
  variables:
    TARGET: x86_64-pc-windows-gnu                        # Windows 64-bit target
  artifacts:
    paths:
      - target/$TARGET/release/mortgage-calculator       # Save the compiled binary
    expire_in: 1 week                                    # Keep artifacts for 1 week
  allow_failure: true                                    # Allow this build to fail (cross-compilation can be tricky)

# Build for macOS x86_64 (cross-compilation)
build-macos:
  extends: .build-template                               # Use build template configuration
  variables:
    TARGET: x86_64-apple-darwin                          # macOS 64-bit target
  artifacts:
    paths:
      - target/$TARGET/release/mortgage-calculator       # Save the compiled binary
    expire_in: 1 week                                    # Keep artifacts for 1 week
  allow_failure: true                                    # Allow this build to fail (cross-compilation can be tricky)

This GitLab CI configuration defines three build jobs that cross-compile a Rust mortgage calculator application for different platforms:

  • build-linux creates a Linux x86_64 binary (required to pass)
  • build-windows creates Windows binaries (allowed to fail)
  • build-macos creates macOS x86_64 binaries (allowed to fail)

All builds use shared templates for dependency caching and consistent build environments.

Testing

GitLab CI/CD streamlines code testing through its integrated pipeline system that automatically triggers test suites whenever code is pushed to the repository. Developers can define multiple types of tests — unit tests, integration tests, linting, and formatting checks — all within a single .gitlab-ci.yml configuration file, with each test running in isolated Docker containers to ensure consistent environments.

# Run unit tests
test:unit:
  extends: .rust-template                                # Use Rust template configuration
  stage: test                                            # Execute during test stage
  script:
    - cargo test --verbose                               # Run all unit tests with verbose output

# Run integration tests using the compiled binary
test:integration:
  extends: .rust-template                                # Use Rust template configuration
  stage: test                                            # Execute during test stage
  script:
    # Test the compiled binary with sample inputs and verify expected output
    - target/x86_64-unknown-linux-gnu/release/mortgage-calculator --cli calculate --property-value 350000 --down-payment 70000 --interest-rate 5.0 | grep -q "TOTAL MONTHLY PAYMENT"
  needs:
    - build-linux                                        # Depends on Linux build job completing

# Run Clippy linter for code quality checks
test:clippy:
  extends: .rust-template                                # Use Rust template configuration
  stage: test                                            # Execute during test stage
  script:
    - rustup component add clippy                        # Install Clippy linter
    - cargo clippy -- -D warnings                       # Run Clippy and treat warnings as errors
  allow_failure: true                                    # Allow linting failures (can be improved over time)

# Check code formatting
test:format:
  extends: .rust-template                                # Use Rust template configuration
  stage: test                                            # Execute during test stage
  script:
    - rustup component add rustfmt                       # Install Rust formatter
    - cargo fmt -- --check                              # Check if code is properly formatted
  allow_failure: true                                    # Allow formatting failures (can be improved over time)

This GitLab CI configuration creates four test jobs that validate a Rust mortgage calculator application:

  • test:unit runs unit tests
  • test:integration executes the compiled Linux binary with sample inputs to verify functionality
  • test:clippy performs code quality linting (allowed to fail)
  • test:format checks code formatting compliance (allowed to fail)

Package and Container Registries

GitLab's Package Registry provides a secure solution to the common challenge of sharing internal libraries and proprietary code within organizations. This capability is essential for enterprises and teams that need to maintain artifacts while leveraging the broader Rust ecosystem.

The registry supports generic artifacts with fine-grained access controls that align with GitLab's project permissions. This means teams can share libraries securely across projects while maintaining intellectual property protection and compliance requirements.

Additonally, we can containerize our application and store the container images in GitLab's built-in Container Registry.

Publishing to GitLab Package Registry

This section of our .gitlab-ci.yml demonstrates how to package and publish Rust applications as tar archives to GitLab's generic package registry using CI/CD automation.

# Package application as tar archive
package:tar:
  image: alpine/curl:8.12.1                             # Lightweight image with curl for uploading
  stage: package                                         # Execute during package stage
  variables:
    PACKAGE_NAME: mortgage-calculator.tar.gz             # Name of the archive file
  script:
    # Create tar archive of the Linux binary
    - tar -czvf $PACKAGE_NAME target/x86_64-unknown-linux-gnu/release/mortgage-calculator
    # Upload archive to GitLab Package Registry using API
    - |
      curl -v --location --header "JOB-TOKEN: $CI_JOB_TOKEN" \
      --upload-file $PACKAGE_NAME \
      "$CI_API_V4_URL/projects/$CI_PROJECT_ID/packages/generic/tar/$CI_COMMIT_BRANCH/$PACKAGE_NAME"
  artifacts:
    paths:
      - target/x86_64-unknown-linux-gnu/release/mortgage-calculator  # Save binary
      - mortgage-calculator.tar.gz                      # Save archive
    expire_in: 1 week                                    # Keep artifacts for 1 week
  needs:
    - build-linux                                        # Depends on Linux build completing

This GitLab CI configuration defines one packaging job package:tar that creates a compressed tar archive of the Linux mortgage calculator binary and uploads it to GitLab's Package Registry, while also saving both the binary and archive as pipeline artifacts.

Package Registry

Publishing to GitLab Container Registry

The below shows the process of building Dockerfiles and publishing Docker images to GitLab's Container Registry with proper tagging and authentication.

# Package application as Docker image
package:docker:
  image: docker:24.0                                     # Use Docker image for building containers
  stage: package                                         # Execute during package stage
  services:
    - docker:24.0-dind                                   # Docker-in-Docker service for building images
  before_script:
    # Login to GitLab Container Registry
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker build -t $DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG .  # Build Docker image with commit SHA tag
    - docker tag $DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG $DOCKER_IMAGE_NAME:latest  # Also tag as latest
    - docker push $DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG  # Push tagged image to registry
    - docker push $DOCKER_IMAGE_NAME:latest             # Push latest image to registry

This GitLab CI configuration defines one Docker packaging job package:docker that builds a Docker image of the mortgage calculator application, tags it with both the commit SHA and "latest," and then pushes both tagged versions to GitLab's Container Registry.

Container Registry

Security scanning

GitLab security scanning provides comprehensive protection that goes beyond Rust's built-in memory safety guarantees. While Rust prevents many common security vulnerabilities at compile time, applications still need protection against dependency vulnerabilities, unsafe code blocks, and logical security issues.

The platform's Static Application Security Testing (SAST) integrates seamlessly with Rust's toolchain, providing automated security analysis as part of the CI/CD pipeline This proactive approach catches security issues before they reach production, supporting both compliance requirements and secure development practices.

GitLab's comprehensive security features including SAST, dependency scanning, secret detection and more can easily be implemented via templates, as seen below. Note: Additional configuration is required to enable SAST for Rust.

# Include GitLab's security scanning templates for DevSecOps
include:
  - template: Jobs/SAST.gitlab-ci.yml                    # Static Application Security Testing
  - template: Jobs/Dependency-Scanning.latest.gitlab-ci.yml  # Scan dependencies for vulnerabilities
  - template: Jobs/Container-Scanning.gitlab-ci.yml      # Scan Docker containers for vulnerabilities
  - template: Jobs/SAST-IaC.gitlab-ci.yml               # Infrastructure as Code security scanning
  - template: Jobs/Secret-Detection.gitlab-ci.yml        # Detect secrets in source code

Security scanners can be configured similar to how you would configure any GitLab job:

# Configure Semgrep SAST scanning for Rust files
semgrep-sast:
  rules:
    - if: $CI_COMMIT_BRANCH                              # Run on any branch
      exists:
        - "**/*.rs"                                      # Only if Rust files exist
  variables:
    SAST_EXCLUDED_PATHS: ".cargo/**"                     # Exclude Cargo cache from scanning

# Scan Docker container for security vulnerabilities
container_scanning:
  stage: container-security                              # Execute during container-security stage
  variables:
    CS_IMAGE: $DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG      # Image to scan
    CS_DOCKERFILE_PATH: Dockerfile                       # Path to Dockerfile for context
  needs:
    - package:docker                                     # Depends on Docker image being built

When vulnerabilites are detected in a merge request (MR), you can see all the vulnerabilites detected and use the provided information to either resolve or dismiss vulnerabilities.

Vulnerability MR view

You also can add Security Policies to require approval before vulnerable code can be merged, or to force scanners to run regardless of what is in the .gitlab-ci.yml.

Merge Request Approval Policy

You can triage all the vulnerabilities found in your default branch by using the Vulnerability Report:

Vulnerability Report

Documentation with GitLab Pages

GitLab Pages provides an excellent platform for hosting Rust documentation, integrating seamlessly with Cargo's built-in documentation generation. This creates a powerful workflow where API documentation, project guides, and examples are automatically generated and deployed with every code change.

The combination of cargo doc and GitLab Pages enables teams to maintain up-to-date documentation without manual intervention, ensuring that documentation stays synchronized with code changes. This is particularly valuable for Rust projects where comprehensive documentation is essential to understand complex APIs and safety contracts.

Automated documentation deployment

The following code shows the CI/CD configuration for automatically generating and deploying Rust documentation using cargo doc and GitLab Pages.

# Generate and publish documentation using GitLab Pages
build-documentation:
  extends: .rust-template                                # Use Rust template configuration
  stage: build                                           # Execute during build stage
  variables:
    GIT_SUBMODULE_STRATEGY: recursive                    # Clone submodules recursively if needed
  pages: true                                            # Enable GitLab Pages deployment
  script:
    - cargo doc --no-deps                                # Generate documentation without dependencies
    - mv target/doc public                               # Move docs to public directory for Pages
  artifacts:
    paths:
      - public                                           # GitLab Pages serves from public directory
  rules:
    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH     # Only run on default branch (main/master)
  environment:
    name: documentation                                  # Environment name for tracking
    url: $CI_PAGES_URL/mortgage_calculator/index.html   # Documentation URL
  allow_failure: true                                    # Allow documentation build to fail

Once the job is complete, you can see the deployed documentation by visiting the GitLab Environment it has been deployed to.

Pages environment

This allows you to manage multiple versions of the documentation in different envrionments. The documentation will be deployed consistent with the cargo doc output:

Pages build

Deploy anywhere

One of GitLab's greatest strengths is its infrastructure-agnostic approach to deployment. Whether your organization runs on traditional on-premises servers, modern cloud platforms, hybrid environments, or edge computing infrastructure, GitLab's CI/CD system can deploy Rust applications seamlessly across any target environment.

GitLab's deployment flexibility stems from its container-first approach and extensive integration ecosystem. The platform supports deployment to virtually any infrastructure that can run containers, virtual machines, or bare-metal applications. This versatility is particularly valuable for Rust applications, which often need to run in diverse environments ranging from resource-constrained embedded systems to high-performance cloud clusters.

Kubernetes deployment

GitLab simplifies Kubernetes deployments by providing built-in cluster integration and pre-configured Docker images that include essential tools like Helm and kubectl, eliminating the need for developers to set up complex deployment environments.

# Deploy application to Kubernetes cluster
deploy:kubernetes:
  stage: deploy                                          # Execute during deploy stage
  image: registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image:helm-3.10.0-kube-1.24.6-alpine-3.15  # Image with Helm and kubectl
  variables:
    HELM_HOST: "localhost:44134"                         # Helm host configuration
    HELM_DEPLOY_NAME: mortgage-calc-$CI_COMMIT_REF_NAME  # Deployment name based on branch
    HELM_DEPLOY_NAMESPACE: calc-app                      # Kubernetes namespace for deployment
    KUBE_CONTEXT: $CI_PROJECT_PATH:rust-mortgage-calculator  # Kubernetes context to use
  script:
    - kubectl config use-context $KUBE_CONTEXT          # Set the kubectl context
    # Deploy using Helm with custom values and Docker image
    - helm upgrade --install $HELM_DEPLOY_NAME chart -f chart/values.yaml
      --namespace $HELM_DEPLOY_NAMESPACE
      --create-namespace
      --set image=$DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG
      --set calc.name=$HELM_DEPLOY_NAME 
  needs:
    - package:docker                                     # Depends on Docker image being available

This GitLab CI configuration defines one deployment job deploy:kubernetes that uses Helm to deploy the mortgage calculator application to a Kubernetes cluster, creating or upgrading the deployment in a dedicated namespace while using the Docker image built in the previous packaging stage.

Kubernetes output

GitLab Duo AI features

GitLab Duo AI features provide significant advantages for Rust development by offering intelligent code suggestions and explanations specifically tailored to the language's unique syntax and patterns.

The GitLab platform supports Rust as one of its directly-supported languages for every IDE, ensuring high-quality code completion and generation that understands Rust's ownership model, memory safety principles, and idiomatic patterns.

GitLab Duo Code Suggestions

GitLab Duo's ability to provide contextual code suggestions while typing helps developers navigate Rust's sometimes complex syntax more efficiently, reducing the learning curve for newcomers and accelerating productivity for experienced developers.

Code Suggestions

GitLab Duo Chat

GitLab Duo Chat complements the code suggestions by offering conversational assistance for explaining Rust code sections, debugging compiler errors, and providing guidance on best practices. This is particularly valuable in Rust development where compiler error messages, while helpful, can sometimes be overwhelming for developers transitioning from other languages. The AI can help interpret Rust's detailed error messages and suggest fixes, making the development process more efficient by reducing the time spent deciphering compilation issues.

GitLab Duo Chat

GitLab Duo Chat can also be used directly from Vulnerability Report to explain a vulnerability. GitLab Duo Vulnerability Explanation represents a significant advancement in making application security more accessible and actionable for development teams. Rather than simply flagging potential issues with cryptic error codes. or technical jargon, AI breaks down each vulnerability's nature, potential impact, and remediation steps in terms that developers at all skill levels can quickly grasp. This democratization of security knowledge accelerates the remediation process, reduces the back-and-forth between security and development teams, and ultimately helps organizations ship more secure code faster:

Vulnerability Explain 1

Vulnerability Explain 2

Vulnerability Explain 3

Vulnerability Explain 4

GitLab Duo also provides Agentic Chat, which serves as an intelligent development companion for Rust applications, offering context-aware assistance throughout the entire development lifecycle. Developers can leverage its conversational interface to generate Rust code snippets, scaffold new Rust projects with appropriate Cargo.toml configurations, and much more.

GitLab Duo Vulnerability Resolution

GitLab Duo Vulnerability Resolution uses AI to automatically generate specific code fixes for detected security issues, dramatically reducing remediation time from hours to minutes. AI analyzes vulnerable code patterns and proposes precise patches tailored to the project's context, language, and dependencies while maintaining code functionality and style consistency. This automation is particularly effective for common vulnerabilities like SQL injection and cross-site scripting, enabling development teams to maintain velocity while significantly improving their security posture without disrupting the development workflow.

Duo Remediate Example 1

Duo Remediate Example 2

GitLab Duo Code Review

GitLab Duo's AI-powered code review enhances the development process by providing intelligent, automated feedback on MRs before human reviewers engage. AI analyzes code changes for potential bugs, security vulnerabilities, performance issues, and adherence to coding standards, offering contextual suggestions and explanations that help developers catch issues early. By augmenting traditional peer reviews with consistent, immediate AI insights, this feature reduces the burden on senior developers, accelerates the review cycle, and ensures that basic quality checks are consistently applied across all code contributions, ultimately improving code quality while allowing human reviewers to focus on higher-level architectural and business logic concerns.

Duo Code Review 1

Duo Code Review 2

These are just some of the AI feautures that can be used to allow you to ship more secure Rust software faster than ever. To learn about all the GitLab AI features provided, visit the GitLab Duo solution page.

The GitLab advantage for Rust

GitLab provides a complete development platform that matches Rust's comprehensive approach:

Integrated Workflow:

  • Single Platform: Code, CI/CD, security, and deployment in one place
  • Rust-optimized: Docker-based builds perfect for Rust's toolchain
  • Security First: Built-in security scanning
  • Enterprise-ready: Scalable infrastructure for large teams

Performance Benefits:

  • Efficient Caching: Speeds up Rust's longer compilation times
  • Parallel Builds: Maximizes GitLab Runner efficiency
  • Artifact Management: Streamlined binary distribution

Developer Experience:

  • Familiar Tools: Leverage standard Rust tooling (Cargo, Clippy, rustfmt)
  • Visual Feedback: Comprehensive dashboards and reporting
  • Automation: Reduces manual deployment and testing overhead
  • GitLab Duo AI: Ship more secure software faster with AI throughout the entire software development lifecycle

GitLab's platform capabilities perfectly complement Rust's strengths, creating an ecosystem where safety, performance, and developer productivity converge. Rust applications on GitLab represent the cutting edge of software development—powered by a platform that understands and enhances the Rust development experience.

To learn more about the benefits of GitLab, sign up for a free trial of GitLab Ultimate with Duo Enterprise.

We want to hear from you

Enjoyed reading this blog post or have questions or feedback? Share your thoughts by creating a new topic in the GitLab community forum.
Share your feedback

50%+ of the Fortune 100 trust GitLab

Start shipping better software faster

See what your team can do with the intelligent

DevSecOps platform.