This code has been moved into https://github.com/sourcegraph/sourcegraph-basic-code-intel/.
This extension provides Go code intelligence on Sourcegraph.
This extension is configured to talk to a language server over WebSockets. If you are running a
private Sourcegraph instance, you should run your own language server. The server is available as a
Docker image sourcegraph/lang-go
from Docker Hub.
If you have private code, we recommend deploying the language server behind an auth proxy (such as the example below using HTTP basic authentication in NGINX), a firewall, or a VPN.
You can prevent unauthorized access to the language server by enforcing HTTP basic authentication in nginx, which comes with the sourcegraph/server image. At a high level, you'll create a secret then put it in both the nginx config and in your Sourcegraph global settings so that logged-in users are authenticated when their browser makes requests to the Go language server.
Here's how to set it up:
Create an .htpasswd
file in the Sourcegraph config directory with one entry:
$ htpasswd -c ~/.sourcegraph/config/.htpasswd langserveruser
New password:
Re-type new password:
Adding password for user langserveruser
Add a location directive the nginx.conf that will route requests to the Go language server:
...
http {
...
server {
...
location / {
...
}
location /go {
proxy_pass http://host.docker.internal:4389;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
auth_basic "basic authentication is required to access the language server";
auth_basic_user_file /etc/sourcegraph/.htpasswd;
}
}
}
- If you're running the quickstart on Linux, change
host.docker.internal
to the output ofip addr show docker0 | grep -Po 'inet \K[\d.]+'
. - If you're using Kubernetes (e.g. deploy-sourcegraph), change
host.docker.internal
tolang-go
.
Add these to your Sourcegraph global settings:
"go.serverUrl": "ws://langserveruser:PASSWORD@example.host.docker.internal:7080/go",
"go.sourcegraphUrl": "http://example.host.docker.internal:7080",
Fill in the PASSWORD
that you created above.
- If you're running the quickstart on macOS, change
example.host.docker.internal
tohost.docker.internal
. - If you're running the quickstart on Linux, change
example.host.docker.internal
to the output ofip addr show docker0 | grep -Po 'inet \K[\d.]+'
. - If you're using Kubernetes (e.g. deploy-sourcegraph):
go.serverUrl
is the address of the Go language server from the perspective of a user's browser (e.g. https://sourcegraph.example.com/go)go.sourcegraphUrl
is the address of the Sourcegraph instance from the perspective of the Go language server (e.g. http://sourcegraph-frontend:30080)
Finally, restart the sourcegraph/server container (or nginx deployment if deployed to Kubernetes) to pick up the configuration change.
After deploying the language server, unauthenticated access to http://localhost:7080/go
(or https://sourcegraph.example.com/go) should be blocked, but code intelligence should work when you're logged in.
You can always revoke the PASSWORD
by deleting the .htpasswd
file and restarting nginx.
-
Run the Go language server:
docker run --rm --name lang-go -p 4389:4389 sourcegraph/lang-go \ go-langserver -mode=websocket -addr=:4389 -usebuildserver -usebinarypkgcache=false -freeosmemory=false
You can verify it's up and running with
ws
(run this from the same machine your browser is running on):$ go get -u github.com/hashrocket/ws $ ws ws://localhost:4389 >
-
Enable this extension on your Sourcegraph https://sourcegraph.example.com/extensions/sourcegraph/go
-
Add these to your Sourcegraph settings in https://sourcegraph.example.com/site-admin/global-settings and make sure the port matches either the Docker command or your Kubernetes config:
"go.serverUrl": "ws://localhost:4389", "go.sourcegraphUrl": "http://host.docker.internal:7080",
If you're running on Linux, change
go.sourcegraphUrl
to the IP given by:ip addr show docker0 | grep -Po 'inet \K[\d.]+'
Now visit a Go file and you should see code intelligence!
Here's a sample Kubernetes configuration:
apiVersion: v1
kind: Service
metadata:
annotations:
prometheus.io/port: "6060"
prometheus.io/scrape: "true"
labels:
app: lang-go
name: lang-go
namespace: prod
spec:
loadBalancerIP: your.static.ip.address
ports:
- name: debug
port: 6060
targetPort: debug
- name: lsp
port: 443
targetPort: lsp
selector:
app: lang-go
type: LoadBalancer
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
annotations:
description: Go code intelligence provided by lang-go
name: lang-go
namespace: prod
spec:
minReadySeconds: 10
replicas: 1
revisionHistoryLimit: 10
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
labels:
app: lang-go
spec:
containers:
- args:
- go-langserver
- -mode=websocket
- -addr=:4389
- -usebuildserver
- -usebinarypkgcache=false
- -cachedir=$(CACHE_DIR)
- -freeosmemory=false
env:
- name: LIGHTSTEP_ACCESS_TOKEN
value: '???'
- name: LIGHTSTEP_INCLUDE_SENSITIVE
value: "true"
- name: LIGHTSTEP_PROJECT
value: sourcegraph-prod
# TLS is optional
- name: TLS_CERT
valueFrom:
secretKeyRef:
key: cert
name: tls
- name: TLS_KEY
valueFrom:
secretKeyRef:
key: key
name: tls
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: CACHE_DIR
value: /mnt/cache/$(POD_NAME)
image: sourcegraph/lang-go:latest
livenessProbe:
initialDelaySeconds: 5
tcpSocket:
port: lsp
timeoutSeconds: 5
name: lang-go
ports:
- containerPort: 4389
name: lsp
- containerPort: 6060
name: debug
readinessProbe:
tcpSocket:
port: 4389
resources:
limits:
cpu: "8"
memory: 10G
requests:
cpu: "1"
memory: 10G
volumeMounts:
- mountPath: /mnt/cache
name: cache-ssd
volumes:
- hostPath:
path: /mnt/disks/ssd0/pod-tmp
name: cache-ssd
🚨 Before mounting your credentials into the language server, make sure the language server is hidden behind an auth proxy or firewall. 🚨
Make sure your $HOME/.netrc
contains:
machine codeload.github.com
login <your username>
password <your password OR access token>
Mount it into the container:
docker run ... -v "$HOME/.netrc":/root/.netrc ...
Verify fetching works:
$ docker exec -ti lang-go sh
# curl -n https://codeload.github.com/you/your-private-repo/zip/master
HTTP/1.1 200 OK
...
Make sure your ~/.gitconfig
contains these lines:
[url "git@github.com:"]
insteadOf = https://github.com/
Mount that and your SSH keys into the container:
docker run ... -v "$HOME/.gitconfig":/root/.gitconfig -v "$HOME/.ssh":/root/.ssh ...
Verify cloning works:
$ docker exec -ti lang-go sh
# git clone https://github.com/you/your-private-repo
Cloning into 'your-private-repo'...
LSIF support can be enabled by setting:
"codeIntel.lsif": true
You can run multiple instances of the go-langserver and distribute connections between them in Kubernetes by setting spec.replicas
in the deployment YAML:
spec:
minReadySeconds: 10
- replicas: 1
+ replicas: 5
revisionHistoryLimit: 10
This extension communicates from your browser to the language server that you deployed over WebSockets. This means that when you're viewing a code file on Sourcegraph, you can open the browser developer tools and refresh the page to capture the WebSocket connection and view the messages being sent and received: