Set up local development environment
Set up your local development environment to work on the Remote Development Workspaces features. You can choose between two setup modes depending on your development needs:
Agent for workspace (
agentw
):- Simpler setup.
- Uses direct agent communication.
- Recommended for most development scenarios.
GitLab Workspaces Proxy:
- More complex setup.
- Uses proxy for workspace communication.
- Required for testing proxy-specific features.
Set up Kubernetes
Install Rancher Desktop 1.20.0.
In Rancher Desktop, select the Preferences icon.
Configure the virtual machine:
Go to Virtual Machine > Hardware and set minimum values of 4 CPUs and 8 GB RAM.
For macOS only:
- Go to Virtual Machine > Emulation
- Select VZ as the Virtual Machine Type.
- Select Enable Rosetta support.
Go to Container Engine, select
containerd
.Go to Kubernetes:
- Select Kubernetes version v1.33.4.
- Clear the Enable Traefik checkbox.
Set up GDK
Set the
GDK_ROOT
environment variable:echo 'export GDK_ROOT="/path/to/your/gdk"' >> ~/.zshrc
Replace
/path/to/your/gdk
with your actual GDK directory path.Configure GDK to run on a local private IP address by following the local network binding documentation.
For this setup, we assume the private IP address is
172.16.123.1
. If you use a different IP address, substitute the correct value in later steps.Configure NGINX for GDK:
Add this configuration to your
gdk.yml
file:hostname: gdk.test nginx: enabled: true http: enabled: true
Install NGINX:
brew install nginx
Optional. Check out the desired branches on GitLab:
cd "${GDK_ROOT}/gitlab" git checkout my_branch
To prevent changes from being lost when you run
gdk update
, add this to yourgdk.yml
:gdk: auto_rebase_projects: true
Restart your GDK:
cd "${GDK_ROOT}" gdk restart
Set up GitLab Agent Server (KAS) in GDK
Enable agent for Kubernetes in your GDK by adding this configuration to
gdk.yml
:gitlab_k8s_agent: enabled: true agent_listen_address: gdk.test:8150 k8s_api_listen_address: gdk.test:8154
Reconfigure and restart GDK:
cd "${GDK_ROOT}" gdk reconfigure gdk restart
Optional. Check out the desired branches on agent for Kubernetes:
cd "${GDK_ROOT}/gitlab-k8s-agent" git checkout my_branch
Optional. To manually run
kas
, for example, to run in a different cloned directory or debug in an IDE:For debugging with JetBrains GoLand IDE:
- Set up a
kas
“Run Configuration” “Run Kind: Directory' - Point to
/path/to/cmd/kas
. - Check
Run after build
. - Pass all the same
ENV
vars and options as you do to Bazel.
- Set up a
Verify agent for Kubernetes installation
To ensure agent for Kubernetes is properly installed:
Install Xcode from the Apple App Store and accept the license:
sudo xcodebuild -license accept
Clone the agent repository:
git clone https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent
Test the installation:
cd gitlab-agent make test
If you encounter errors, clean and retry:
bazel clean --expunge make test
You might also need to do this in the
<GDK_ROOT>/gitlab-k8s-agent
, which is used by the GDK.
When make test
passes, agent for Kubernetes is ready to use.
Set up agent for Kubernetes (agentk
) for Workspaces
Create an agent configuration file:
- Go to
http://gdk.test:3000/gitlab-org
. - Create a private project named
gitlab-agent-configurations
with a README. - In the project, create a file at
.gitlab/agents/remotedev/config.yaml
with youragentk
configuration.
When you create or change this file, you must start or restart
agentk
described in step 4.- Go to
Register
agentk
with GitLab:- In the
gitlab-agent-configurations
project, go to Operate > Kubernetes clusters. - Select Connect a cluster.
- Enter
remotedev
in the input field. - Select Register.
- Copy and save the generated token. It is required for the
AGENT_TOKEN
environment variable.
- In the
Map the agent to the
gitlab-org
group:- Go to
http://gdk.test:3000/gitlab-org
. - Go to Settings > Workspaces.
- Select the All agents tab.
- Find
remotedev
in the list and select Allow. - Verify the agent appears in the Allowed agents tab.
- Go to
Start the Agent (
agentk
):export AGENT_TOKEN='your_copied_token' cd "${GDK_ROOT}/gitlab-k8s-agent" echo -n "$AGENT_TOKEN" > "$HOME/.gitlab-agentk-token.txt" export POD_NAMESPACE=default export POD_NAME=remotedev bazel run //cmd/agentk -- --kas-address=grpc://gdk.test:8150 --token-file=$HOME/.gitlab-agentk-token.txt
Optional. To manually run
agentk
, for example, to run in a different cloned dir or debug in an IDE:For debugging with JetBrains GoLand IDE:
- Set up a
kas
“Run Configuration” “Run Kind: Directory' - Point to
/path/to/cmd/kas
. - Check
Run after build
. - Pass all the same
ENV
vars and options as you do to Bazel.
- Set up a
Go to Operate > Kubernetes clusters. The remotedev
agent should now display as Connected.
Configure Workspaces in GDK
For agent for workspace mode
Use this configuration in the .gitlab/agents/remotedev/config.yaml
file:
remote_development:
enabled: true
network_policy:
enabled: true
egress:
- allow: '0.0.0.0/0'
except:
- '10.0.0.0/8'
- '172.16.0.0/12'
- '192.168.0.0/16'
- allow: '172.16.123.1/32'
gitlab_workspaces_proxy:
http_enabled: false
ssh_enabled: false
observability:
logging:
level: debug
grpc_level: warn
For GitLab Workspaces Proxy mode
Use this configuration in the .gitlab/agents/remotedev/config.yaml
file:
remote_development:
enabled: true
dns_zone: workspaces.localtest.me
network_policy:
enabled: true
egress:
- allow: '0.0.0.0/0'
except:
- '10.0.0.0/8'
- '172.16.0.0/12'
- '192.168.0.0/16'
- allow: '172.16.123.1/32'
observability:
logging:
level: debug
grpc_level: warn
Set up GitLab Workspaces Proxy (proxy mode only)
If you chose the GitLab Workspaces Proxy mode, complete these additional steps:
Create an OAuth application:
Go to
http://gdk.test:3000/admin
.Go to Applications and select Add new application.
Set the name to
GitLab Workspaces Proxy
.Set the redirect URI to
https://workspaces.localtest.me/auth/callback
.Set the scopes to
api
,read_user
,openid
, andprofile
.Export the client credentials:
export CLIENT_ID="your_client_id" export CLIENT_SECRET="your_client_secret"
Export
GITLAB_URL
to point to your GDK:export GITLAB_URL="http://gdk.test:3000"
Set up Ingress Controller and GitLab Workspaces Proxy:
brew install mkcert cd "${GDK_ROOT}/gitlab" ./scripts/remote_development/workspaces_kubernetes_setup.sh
Create a workspace
Optional. Define a devfile for testing:
If you don’t need to test specific configurations, skip this step in favor of using the default Devfile in the next step.
Go to the
gitlab-org/gitlab-shell
project athttp://gdk.test:3000/gitlab-org/gitlab-shell
.Create a file at
.devfile.yaml
:schemaVersion: 2.2.0 components: - name: tooling-container attributes: gl/inject-editor: true container: image: "registry.gitlab.com/gitlab-org/workspaces/gitlab-workspaces-docs/ubuntu:04@sha256:07590ca30ebde8a5339c3479404953e43ee70e7e9e0c2ede2770684010ddf7fe"
The SHA256 is required to ensure the pulled container is the AMD64 architecture container. The GitLab VS Code fork for Workspaces does not support other architectures yet. To track this, see issue 392693.
Create a new workspace:
Go to Your Work > Workspaces at
http://gdk.test:3000/-/remote_development/workspaces
.Select New Workspace.
Choose the project with your devfile (or search for
shell
to find GitLab Shell).If you get an error about a missing agent configuration, check your
agentk
debug logs to ensure that youragentk
successfully connects and reads your agent configuration file.Choose your cluster agent.
If you skipped the devfile step, select Use GitLab default devfile.
Select Create Workspace.
Wait for the workspace to reach the Running state.
Select Open Workspace.
To enable Extensions Marketplace for Web IDE in a workspace, see manage extensions.
By default, the GitLab VS Code fork for Workspaces server uses Open VSX Extensions Marketplace. These settings are configured during a workspace startup in the
product.json
file. This file is located in the${GL_EDITOR_VOLUME_DIR}/code-server
directory.To customize the Extensions Marketplace configuration, these are the relevant properties in the
product.json
file:{ "extensionsGallery": { "serviceUrl": "", "itemUrl": "", "resourceUrlTemplate": "" } }
Optional. Set up AI features
To enable AI features in workspaces:
Follow the instructions in Set up GitLab Team Member License for GDK.
This page also lists other set up AI features options for local development. To provision a GitLab Self-Managed Ultimate Subscription with Duo Pro add-on license yourself, follow the cloud license with CustomersDot approach.
Configure your instance to use the staging AI gateway (
https://cloud.staging.gitlab.com/ai
).
For workspaces, you must enable Duo Chat features. They are only available with a Duo Enterprise
license. You cannot provision this license for yourself through the staging Customers Portal.
To upgrade your subscription from Duo Pro to Duo Enterprise, submit your request in the
#g_provision
Slack channel.
If configured correctly, in the Admin > GitLab Duo Pro settings, the message, No health problems detected. is displayed.
While using Duo Chat, if you see the Error code: A9999
response, clear and reset the chat until it succeeds.
It is a common error response from the GitLab Duo API when using the staging gateway.
IDE Setup
RubyMine
It is planned to move some of the information in this section to the RubyMine handbook section, or ideally shared with SCM.
Scopes
Use these scopes to:
- Search code in the scope.
Inspect Code
(cmd-shift-A -> Inspect Code
) to run static analysis on the scope.
remote_dev
file[gitlab]:ee/lib/remote_development//*||file[gitlab]:ee/spec/factories/remote_development//*||file[gitlab]:ee/app/services/remote_development//*||file[gitlab]:app/models/remote_development//*||file[gitlab]:ee/app/graphql/mutations/remote_development//*||file[gitlab]:ee/app/graphql/resolvers/remote_development//*||file[gitlab]:ee/app/graphql/types/remote_development//*||file[gitlab]:ee/app/models/remote_development//*||file[gitlab]:ee/spec/graphql/types/remote_development//*||file[gitlab]:ee/spec/models/remote_development//*||file[gitlab]:ee/spec/services/remote_development//*||file[gitlab]:ee/app/finders/remote_development//*||file[gitlab]:ee/spec/features/remote_development//*||file[gitlab]:ee/spec/support/shared_contexts/remote_development//*||file[gitlab]:ee/app/graphql/ee/types/user_interface.rb||file[gitlab]:ee/app/graphql/resolvers/concerns/remote_development//*||file[gitlab]:ee/app/graphql/resolvers/projects/workspaces_resolver.rb||file[gitlab]:ee/app/graphql/resolvers/users/workspaces_resolver.rb||file[gitlab]:ee/spec/requests/api/graphql/mutations/remote_development//*||file[gitlab]:ee/spec/requests/api/graphql/remote_development//*||file[gitlab]:ee/spec/finders/remote_development//*||file[gitlab]:ee/app/assets/javascripts/remote_development//*||file[gitlab]:ee/spec/frontend/remote_development//*||file[gitlab]:ee/spec/graphql/api/workspace_spec.rb||file[gitlab]:ee/spec/fixtures/remote_development//*||file[gitlab]:ee/spec/lib/remote_development//*
remote_dev services & lib
Use this scope to set up restricted YARD
inspections and to have safety warnings for:
Editor -> Inspections -> YARD -> Missing @param tag in method signature
, add scope asWarning
Editor -> Inspections -> YARD -> Missing @return tag in method
, add scope asWarning
file[gitlab]:ee/app/services/remote_development//*||file[gitlab]:ee/lib/remote_development//*
Testing
Run test suite
To run a subset of specs related to the Workspaces feature for a pre-commit “Smoke Test”, use the following script:
scripts/remote_development/run-smoke-test-suite.sh
Run E2E spec locally
- There is an end to end test that verifies the creation of a new running workspace.
- The test works by running UI actions on a running installation of a test GitLab instance, using GDK, KAS, and
agentk
.
The test does not set up or teardown any of these components as a part of its execution.
At present, the test is tagged with a quarantine
label so it does not run as a part of CI/CD, because
of complexities in spinning up KAS and agentk
in the CI/CD environment. It must be run manually.
To run the test:
Ensure that the test GitLab instance is up and running with the default KAS or
agentk
stopped.Ensure KAS with remote development code is up and running.
By default, the E2E test assumes the existence of an agent with name
test-agent
under the groupgitlab-org
in the GDK GitLab instance:- To work with the defaults, create an agent with the name
test-agent
in a project ingitlab-org
group. Thegitlab-shell
project in thegitlab-org
group is a candidate for where to create this agent. - Alternatively, to use a custom group/agent, override the group and agent name with the environment
variables
AGENTK_GROUP
andAGENTK_NAME
.
- To work with the defaults, create an agent with the name
Change the current working directory to
{GDK_ROOT}/gitlab
.Run the test with
scripts/remote_development/run-e2e-spec.sh
.- To override the defaults, use
AGENTK_GROUP=some-org GITLAB_PASSWORD=example scripts/remote_development/run-e2e-spec.sh
The complete list of environment variables are in
scripts/remote_development/run-e2e-spec.sh
.- To override the defaults, use
Verify behavior with example projects
Use the example projects to test GitLab Workspaces. These projects include devfiles and work out-of-the-box.
- Clone the example projects to your development machine and push them to your local GitLab installation
as public projects under the
gitlab-org
group. - The projects appear in the project list when you create a workspace.
- Follow the
README
file in each project for specific usage instructions.
Repositories
These repositories are used to develop Workspaces:
Name | Description | Language |
---|---|---|
GitLab | Main logic | Ruby on Rails |
GitLab Agent for Kubernetes | Logic for creating/report Kubernetes resources | Go |
GitLab Workspaces Proxy | Logic for authentication and authorization of incoming workspaces traffic | Go |
GitLab Build Images | Logic for workspaces-related container image builds | Shell script, Docker |
Devfile Gem | Logic for converting Devfile to Kubernetes resources | Go, Ruby |
These dependencies are external repositories that Workspaces relies on:
Name | Description | Language | Used by |
---|---|---|---|
GitLab VS Code Fork | GitLab fork of upstream VS Code OSS project | Script | GitLab Workspaces Tools |
GitLab VS Code Extension | GitLab VS Code Extension | TypeScript | GitLab Workspaces Tools |
Devfile API | Upstream project defining Devfile Schema | Go | GitLab |
Devfile Library | Upstream project for converting Devfile to Kubernetes resources | Go | Devfile Gem |
Debugging
IDE setup for debugging
For tips on debugging under Ruby Mine, see Using RubyMine debugger for GitLab running under GDK.
KAS and agentk
debugging also works under GoLand. If you need help to set up Run Configurations,
reach out to one of the developers or engineers.
Rails
log/remote_development.log
log/remote_development.log
contains specific remote development logs in JSON format.
You might need to install jq
.
tail -f log/remote_development.log | jq
log/development.log
For other details or exceptions that are not in log/remote_development.log
, see the standard Rails log/development.log
:
tail -f log/development.log
Delete orphaned workspace in Rails
You might get orphaned workspace records on Rails, or you might want to start with a clean slate. To do this:
Go to the
gitlab
repository in your GDK.Open the Rails console:
bin/rails c
Delete all the workspace records:
RemoteDevelopment::Workspace.delete_all
Kubernetes
Context and namespace management
Task | Command |
---|---|
List all contexts | kubectl config get-contexts |
Get current context | kubectl config current-context |
Switch context | kubectl config use-context CONTEXT_NAME |
List namespaces | kubectl get namespaces |
Switch namespace | kubectl config set-context --current --namespace=NAMESPACE |
Resource inspection
Task | Command |
---|---|
List pods in all namespaces | kubectl get pods -A |
Get namespace details | kubectl get namespace NAMESPACE -o yaml |
Get pod details | kubectl -n NAMESPACE get pods POD_NAME -o yaml |
List API resources | kubectl api-resources |
If you omit -n NAMESPACE
from commands, kubectl
uses the current namespace.
Logs and debugging
Get logs from a pod:
kubectl -n NAMESPACE logs -f POD_NAME
Get logs from a specific container:
kubectl -n NAMESPACE logs -f POD_NAME -c CONTAINER_NAME
Workspace-specific commands
Get all workspace objects:
kubectl get serviceaccount,pvc,networkpolicy,resourcequota,deployment,service,secret,configmap -l "agent.gitlab.com/id"
Get the gitlab-workspaces-proxy-config
secret:
kubectl -n gitlab-workspaces get secret gitlab-workspaces-proxy-config -o go-template='{{range $k,$v := .data}}{{printf "%s: " $k}}{{if not $v}}{{$v}}{{else}}{{$v | base64decode}}{{end}}{{"\n"}}{{end}}'
Enter workspace main container shell:
PODNAME=$(kubectl get po -o name | cut -d/ -f2) && CONTAINER_NAME=$(kubectl get pod $PODNAME -o jsonpath='{range .spec.containers[*]}{.name}{"\t"}{range .env[*]}{.name}{","}{end}{"\n"}{end}' | grep GL_TOOLS_DIR | cut -f 1) && kubectl exec $PODNAME -c $CONTAINER_NAME -it -- /bin/bash
Run commands in the workspace container (example with log tailing):
PODNAME=$(kubectl get po -o name | cut -d/ -f2) && CONTAINER_NAME=$(kubectl get pod $PODNAME -o jsonpath='{range .spec.containers[*]}{.name}{"\t"}{range .env[*]}{.name}{","}{end}{"\n"}{end}' | grep GL_TOOLS_DIR | cut -f 1) && kubectl exec $PODNAME -c $CONTAINER_NAME -it -- /bin/bash -c "tail -n 100 -f /tmp/*.log"
These commands run in the current namespace. Use kubens
to switch to the workspace namespace before
running them.
Cleanup operations
Delete a namespace:
kubectl delete namespace NAMESPACE
Delete a pod:
kubectl -n NAMESPACE delete pods POD_NAME
Delete all workspace namespaces:
kubectl get namespace | grep gl- | cut -f1 -d" " | xargs -I {} kubectl delete namespace {}
This cleanup may take time. If it stalls, restart Rancher Desktop and try again.
Additional resources
For information about how localhost traffic reaches Kubernetes when using GitLab Workspaces Proxy, see this comment.