mirror of
https://github.com/coder/code-server.git
synced 2026-04-16 21:31:43 -05:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94ef3776ad | ||
|
|
a82f1ceaa5 | ||
|
|
25254214fb | ||
|
|
feb5e6770c | ||
|
|
e37b35278d | ||
|
|
2ffbcfdfcb | ||
|
|
74da5167a2 |
23
CHANGELOG.md
23
CHANGELOG.md
@@ -22,6 +22,29 @@ Code v99.99.999
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
## [4.16.0](https://github.com/coder/code-server/releases/tag/v4.16.0) - 2023-07-28
|
||||||
|
|
||||||
|
Code v1.80.1
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- `--disable-proxy` flag. This disables the domain and path proxies but it does
|
||||||
|
not disable the ports panel in Code. That can be disabled by using
|
||||||
|
`remote.autoForwardPorts=false` in your settings.
|
||||||
|
|
||||||
|
## [4.15.0](https://github.com/coder/code-server/releases/tag/v4.15.0) - 2023-07-21
|
||||||
|
|
||||||
|
Code v1.80.1
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Updated to Code 1.80.1.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- `--trusted-origin` flag for specifying origins that you trust but do not
|
||||||
|
control (for example a reverse proxy).
|
||||||
|
|
||||||
Code v1.79.2
|
Code v1.79.2
|
||||||
|
|
||||||
## [4.14.1](https://github.com/coder/code-server/releases/tag/v4.14.1) - 2023-06-26
|
## [4.14.1](https://github.com/coder/code-server/releases/tag/v4.14.1) - 2023-06-26
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ type: application
|
|||||||
# This is the chart version. This version number should be incremented each time you make changes
|
# This is the chart version. This version number should be incremented each time you make changes
|
||||||
# to the chart and its templates, including the app version.
|
# to the chart and its templates, including the app version.
|
||||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||||
version: 3.10.1
|
version: 3.12.0
|
||||||
|
|
||||||
# This is the version number of the application being deployed. This version number should be
|
# This is the version number of the application being deployed. This version number should be
|
||||||
# incremented each time you make changes to the application. Versions are not expected to
|
# incremented each time you make changes to the application. Versions are not expected to
|
||||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||||
appVersion: 4.14.1
|
appVersion: 4.16.0
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ replicaCount: 1
|
|||||||
|
|
||||||
image:
|
image:
|
||||||
repository: codercom/code-server
|
repository: codercom/code-server
|
||||||
tag: '4.14.1'
|
tag: '4.16.0'
|
||||||
pullPolicy: Always
|
pullPolicy: Always
|
||||||
|
|
||||||
# Specifies one or more secrets to be used when pulling images from a
|
# Specifies one or more secrets to be used when pulling images from a
|
||||||
|
|||||||
31
docs/FAQ.md
31
docs/FAQ.md
@@ -14,6 +14,7 @@
|
|||||||
- [How do I install an extension manually?](#how-do-i-install-an-extension-manually)
|
- [How do I install an extension manually?](#how-do-i-install-an-extension-manually)
|
||||||
- [How do I use my own extensions marketplace?](#how-do-i-use-my-own-extensions-marketplace)
|
- [How do I use my own extensions marketplace?](#how-do-i-use-my-own-extensions-marketplace)
|
||||||
- [Where are extensions stored?](#where-are-extensions-stored)
|
- [Where are extensions stored?](#where-are-extensions-stored)
|
||||||
|
- [Where is VS Code configuration stored?](#where-is-vs-code-configuration-stored)
|
||||||
- [How can I reuse my VS Code configuration?](#how-can-i-reuse-my-vs-code-configuration)
|
- [How can I reuse my VS Code configuration?](#how-can-i-reuse-my-vs-code-configuration)
|
||||||
- [How does code-server decide what workspace or folder to open?](#how-does-code-server-decide-what-workspace-or-folder-to-open)
|
- [How does code-server decide what workspace or folder to open?](#how-does-code-server-decide-what-workspace-or-folder-to-open)
|
||||||
- [How do I access my Documents/Downloads/Desktop folders in code-server on macOS?](#how-do-i-access-my-documentsdownloadsdesktop-folders-in-code-server-on-macos)
|
- [How do I access my Documents/Downloads/Desktop folders in code-server on macOS?](#how-do-i-access-my-documentsdownloadsdesktop-folders-in-code-server-on-macos)
|
||||||
@@ -34,6 +35,7 @@
|
|||||||
- [Are there community projects involving code-server?](#are-there-community-projects-involving-code-server)
|
- [Are there community projects involving code-server?](#are-there-community-projects-involving-code-server)
|
||||||
- [How do I change the port?](#how-do-i-change-the-port)
|
- [How do I change the port?](#how-do-i-change-the-port)
|
||||||
- [How do I hide the coder/coder promotion in Help: Getting Started?](#how-do-i-hide-the-codercoder-promotion-in-help-getting-started)
|
- [How do I hide the coder/coder promotion in Help: Getting Started?](#how-do-i-hide-the-codercoder-promotion-in-help-getting-started)
|
||||||
|
- [How do I disable the proxy?](#how-do-i-disable-the-proxy)
|
||||||
- [How do I disable file download?](#how-do-i-disable-file-download)
|
- [How do I disable file download?](#how-do-i-disable-file-download)
|
||||||
|
|
||||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||||
@@ -191,10 +193,20 @@ docs](https://github.com/VSCodium/vscodium/blob/master/DOCS.md#extensions--marke
|
|||||||
|
|
||||||
## Where are extensions stored?
|
## Where are extensions stored?
|
||||||
|
|
||||||
Extensions are store, by default, to `~/.local/share/code-server/extensions`.
|
Extensions are stored in `~/.local/share/code-server/extensions` by default.
|
||||||
|
|
||||||
If you set the `XDG_DATA_HOME` environment variable, the data directory will be
|
On Linux and macOS if you set the `XDG_DATA_HOME` environment variable, the
|
||||||
`$XDG_DATA_HOME/code-server/extensions`. In general, we try to follow the XDG directory spec.
|
extensions directory will be `$XDG_DATA_HOME/code-server/extensions`. In
|
||||||
|
general, we try to follow the XDG directory spec.
|
||||||
|
|
||||||
|
## Where is VS Code configuration stored?
|
||||||
|
|
||||||
|
VS Code configuration such as settings and keybindings are stored in
|
||||||
|
`~/.local/share/code-server` by default.
|
||||||
|
|
||||||
|
On Linux and macOS if you set the `XDG_DATA_HOME` environment variable, the data
|
||||||
|
directory will be `$XDG_DATA_HOME/code-server`. In general, we try to follow the
|
||||||
|
XDG directory spec.
|
||||||
|
|
||||||
## How can I reuse my VS Code configuration?
|
## How can I reuse my VS Code configuration?
|
||||||
|
|
||||||
@@ -453,6 +465,19 @@ You can pass the flag `--disable-getting-started-override` to `code-server` or
|
|||||||
you can set the environment variable `CS_DISABLE_GETTING_STARTED_OVERRIDE=1` or
|
you can set the environment variable `CS_DISABLE_GETTING_STARTED_OVERRIDE=1` or
|
||||||
`CS_DISABLE_GETTING_STARTED_OVERRIDE=true`.
|
`CS_DISABLE_GETTING_STARTED_OVERRIDE=true`.
|
||||||
|
|
||||||
|
## How do I disable the proxy?
|
||||||
|
|
||||||
|
You can pass the flag `--disable-proxy` to `code-server` or
|
||||||
|
you can set the environment variable `CS_DISABLE_PROXY=1` or
|
||||||
|
`CS_DISABLE_PROXY=true`.
|
||||||
|
|
||||||
|
Note, this option currently only disables the proxy routes to forwarded ports, including
|
||||||
|
the domain and path proxy routes over HTTP and WebSocket; however, it does not
|
||||||
|
disable the automatic port forwarding in the VS Code workbench itself. In other words,
|
||||||
|
user will still see the Ports tab and notifications, but will not be able to actually
|
||||||
|
use access the ports. It is recommended to set `remote.autoForwardPorts` to `false`
|
||||||
|
when using the option.
|
||||||
|
|
||||||
## How do I disable file download?
|
## How do I disable file download?
|
||||||
|
|
||||||
You can pass the flag `--disable-file-downloads` to `code-server`
|
You can pass the flag `--disable-file-downloads` to `code-server`
|
||||||
|
|||||||
Submodule lib/vscode updated: 74f6148eb9...2ccd690cbf
@@ -51,6 +51,7 @@ export interface UserProvidedCodeArgs {
|
|||||||
"disable-file-downloads"?: boolean
|
"disable-file-downloads"?: boolean
|
||||||
"disable-workspace-trust"?: boolean
|
"disable-workspace-trust"?: boolean
|
||||||
"disable-getting-started-override"?: boolean
|
"disable-getting-started-override"?: boolean
|
||||||
|
"disable-proxy"?: boolean
|
||||||
"session-socket"?: string
|
"session-socket"?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,6 +179,10 @@ export const options: Options<Required<UserProvidedArgs>> = {
|
|||||||
type: "boolean",
|
type: "boolean",
|
||||||
description: "Disable the coder/coder override in the Help: Getting Started page.",
|
description: "Disable the coder/coder override in the Help: Getting Started page.",
|
||||||
},
|
},
|
||||||
|
"disable-proxy": {
|
||||||
|
type: "boolean",
|
||||||
|
description: "Disable domain and path proxy routes.",
|
||||||
|
},
|
||||||
// --enable can be used to enable experimental features. These features
|
// --enable can be used to enable experimental features. These features
|
||||||
// provide no guarantees.
|
// provide no guarantees.
|
||||||
enable: { type: "string[]" },
|
enable: { type: "string[]" },
|
||||||
@@ -564,6 +569,10 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
|
|||||||
args["disable-getting-started-override"] = true
|
args["disable-getting-started-override"] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (process.env.CS_DISABLE_PROXY?.match(/^(1|true)$/)) {
|
||||||
|
args["disable-proxy"] = true
|
||||||
|
}
|
||||||
|
|
||||||
const usingEnvHashedPassword = !!process.env.HASHED_PASSWORD
|
const usingEnvHashedPassword = !!process.env.HASHED_PASSWORD
|
||||||
if (process.env.HASHED_PASSWORD) {
|
if (process.env.HASHED_PASSWORD) {
|
||||||
args["hashed-password"] = process.env.HASHED_PASSWORD
|
args["hashed-password"] = process.env.HASHED_PASSWORD
|
||||||
|
|||||||
@@ -75,6 +75,25 @@ export const replaceTemplates = <T extends object>(
|
|||||||
.replace("{{OPTIONS}}", () => escapeJSON(serverOptions))
|
.replace("{{OPTIONS}}", () => escapeJSON(serverOptions))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throw an error if proxy is not enabled. Call `next` if provided.
|
||||||
|
*/
|
||||||
|
export const ensureProxyEnabled = (req: express.Request, _?: express.Response, next?: express.NextFunction): void => {
|
||||||
|
if (!proxyEnabled(req)) {
|
||||||
|
throw new HttpError("Forbidden", HttpCode.Forbidden)
|
||||||
|
}
|
||||||
|
if (next) {
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if proxy is enabled.
|
||||||
|
*/
|
||||||
|
export const proxyEnabled = (req: express.Request): boolean => {
|
||||||
|
return !req.args["disable-proxy"]
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throw an error if not authorized. Call `next` if provided.
|
* Throw an error if not authorized. Call `next` if provided.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -144,7 +144,9 @@ export const runCodeServer = async (
|
|||||||
logger.info(" - Not serving HTTPS")
|
logger.info(" - Not serving HTTPS")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args["proxy-domain"].length > 0) {
|
if (args["disable-proxy"]) {
|
||||||
|
logger.info(" - Proxy disabled")
|
||||||
|
} else if (args["proxy-domain"].length > 0) {
|
||||||
logger.info(` - ${plural(args["proxy-domain"].length, "Proxying the following domain")}:`)
|
logger.info(` - ${plural(args["proxy-domain"].length, "Proxying the following domain")}:`)
|
||||||
args["proxy-domain"].forEach((domain) => logger.info(` - ${domain}`))
|
args["proxy-domain"].forEach((domain) => logger.info(` - ${domain}`))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Request, Router } from "express"
|
import { Request, Router } from "express"
|
||||||
import { HttpCode, HttpError } from "../../common/http"
|
import { HttpCode, HttpError } from "../../common/http"
|
||||||
import { getHost, authenticated, ensureAuthenticated, ensureOrigin, redirect, self } from "../http"
|
import { getHost, ensureProxyEnabled, authenticated, ensureAuthenticated, ensureOrigin, redirect, self } from "../http"
|
||||||
import { proxy } from "../proxy"
|
import { proxy } from "../proxy"
|
||||||
import { Router as WsRouter } from "../wsRouter"
|
import { Router as WsRouter } from "../wsRouter"
|
||||||
|
|
||||||
@@ -59,6 +59,8 @@ router.all("*", async (req, res, next) => {
|
|||||||
return next()
|
return next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ensureProxyEnabled(req)
|
||||||
|
|
||||||
// Must be authenticated to use the proxy.
|
// Must be authenticated to use the proxy.
|
||||||
const isAuthenticated = await authenticated(req)
|
const isAuthenticated = await authenticated(req)
|
||||||
if (!isAuthenticated) {
|
if (!isAuthenticated) {
|
||||||
@@ -100,6 +102,8 @@ wsRouter.ws("*", async (req, _, next) => {
|
|||||||
if (!port) {
|
if (!port) {
|
||||||
return next()
|
return next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ensureProxyEnabled(req)
|
||||||
ensureOrigin(req)
|
ensureOrigin(req)
|
||||||
await ensureAuthenticated(req)
|
await ensureAuthenticated(req)
|
||||||
proxy.ws(req, req.ws, req.head, {
|
proxy.ws(req, req.ws, req.head, {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import * as path from "path"
|
|||||||
import * as qs from "qs"
|
import * as qs from "qs"
|
||||||
import * as pluginapi from "../../../typings/pluginapi"
|
import * as pluginapi from "../../../typings/pluginapi"
|
||||||
import { HttpCode, HttpError } from "../../common/http"
|
import { HttpCode, HttpError } from "../../common/http"
|
||||||
import { authenticated, ensureAuthenticated, ensureOrigin, redirect, self } from "../http"
|
import { ensureProxyEnabled, authenticated, ensureAuthenticated, ensureOrigin, redirect, self } from "../http"
|
||||||
import { proxy as _proxy } from "../proxy"
|
import { proxy as _proxy } from "../proxy"
|
||||||
|
|
||||||
const getProxyTarget = (req: Request, passthroughPath?: boolean): string => {
|
const getProxyTarget = (req: Request, passthroughPath?: boolean): string => {
|
||||||
@@ -21,6 +21,8 @@ export async function proxy(
|
|||||||
passthroughPath?: boolean
|
passthroughPath?: boolean
|
||||||
},
|
},
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
ensureProxyEnabled(req)
|
||||||
|
|
||||||
if (!(await authenticated(req))) {
|
if (!(await authenticated(req))) {
|
||||||
// If visiting the root (/:port only) redirect to the login page.
|
// If visiting the root (/:port only) redirect to the login page.
|
||||||
if (!req.params[0] || req.params[0] === "/") {
|
if (!req.params[0] || req.params[0] === "/") {
|
||||||
@@ -50,6 +52,7 @@ export async function wsProxy(
|
|||||||
passthroughPath?: boolean
|
passthroughPath?: boolean
|
||||||
},
|
},
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
ensureProxyEnabled(req)
|
||||||
ensureOrigin(req)
|
ensureOrigin(req)
|
||||||
await ensureAuthenticated(req)
|
await ensureAuthenticated(req)
|
||||||
_proxy.ws(req, req.ws, req.head, {
|
_proxy.ws(req, req.ws, req.head, {
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ describe("parser", () => {
|
|||||||
delete process.env.CS_DISABLE_FILE_DOWNLOADS
|
delete process.env.CS_DISABLE_FILE_DOWNLOADS
|
||||||
delete process.env.CS_DISABLE_GETTING_STARTED_OVERRIDE
|
delete process.env.CS_DISABLE_GETTING_STARTED_OVERRIDE
|
||||||
delete process.env.VSCODE_PROXY_URI
|
delete process.env.VSCODE_PROXY_URI
|
||||||
|
delete process.env.CS_DISABLE_PROXY
|
||||||
console.log = jest.fn()
|
console.log = jest.fn()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -103,6 +104,8 @@ describe("parser", () => {
|
|||||||
|
|
||||||
"--disable-getting-started-override",
|
"--disable-getting-started-override",
|
||||||
|
|
||||||
|
"--disable-proxy",
|
||||||
|
|
||||||
["--session-socket", "/tmp/override-code-server-ipc-socket"],
|
["--session-socket", "/tmp/override-code-server-ipc-socket"],
|
||||||
|
|
||||||
["--host", "0.0.0.0"],
|
["--host", "0.0.0.0"],
|
||||||
@@ -123,6 +126,7 @@ describe("parser", () => {
|
|||||||
},
|
},
|
||||||
"disable-file-downloads": true,
|
"disable-file-downloads": true,
|
||||||
"disable-getting-started-override": true,
|
"disable-getting-started-override": true,
|
||||||
|
"disable-proxy": true,
|
||||||
enable: ["feature1", "feature2"],
|
enable: ["feature1", "feature2"],
|
||||||
help: true,
|
help: true,
|
||||||
host: "0.0.0.0",
|
host: "0.0.0.0",
|
||||||
@@ -392,6 +396,30 @@ describe("parser", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should use env var CS_DISABLE_PROXY", async () => {
|
||||||
|
process.env.CS_DISABLE_PROXY = "1"
|
||||||
|
const args = parse([])
|
||||||
|
expect(args).toEqual({})
|
||||||
|
|
||||||
|
const defaultArgs = await setDefaults(args)
|
||||||
|
expect(defaultArgs).toEqual({
|
||||||
|
...defaults,
|
||||||
|
"disable-proxy": true,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should use env var CS_DISABLE_PROXY set to true", async () => {
|
||||||
|
process.env.CS_DISABLE_PROXY = "true"
|
||||||
|
const args = parse([])
|
||||||
|
expect(args).toEqual({})
|
||||||
|
|
||||||
|
const defaultArgs = await setDefaults(args)
|
||||||
|
expect(defaultArgs).toEqual({
|
||||||
|
...defaults,
|
||||||
|
"disable-proxy": true,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
it("should error if password passed in", () => {
|
it("should error if password passed in", () => {
|
||||||
expect(() => parse(["--password", "supersecret123"])).toThrowError(
|
expect(() => parse(["--password", "supersecret123"])).toThrowError(
|
||||||
"--password can only be set in the config file or passed in via $PASSWORD",
|
"--password can only be set in the config file or passed in via $PASSWORD",
|
||||||
|
|||||||
@@ -45,6 +45,17 @@ describe("proxy", () => {
|
|||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should return 403 Forbidden if proxy is disabled", async () => {
|
||||||
|
e.get("/wsup", (req, res) => {
|
||||||
|
res.json("you cannot see this")
|
||||||
|
})
|
||||||
|
codeServer = await integration.setup(["--auth=none", "--disable-proxy"], "")
|
||||||
|
const resp = await codeServer.fetch(proxyPath)
|
||||||
|
expect(resp.status).toBe(403)
|
||||||
|
const json = await resp.json()
|
||||||
|
expect(json).toEqual({ error: "Forbidden" })
|
||||||
|
})
|
||||||
|
|
||||||
it("should rewrite the base path", async () => {
|
it("should rewrite the base path", async () => {
|
||||||
e.get("/wsup", (req, res) => {
|
e.get("/wsup", (req, res) => {
|
||||||
res.json("asher is the best")
|
res.json("asher is the best")
|
||||||
|
|||||||
Reference in New Issue
Block a user