-diff --git a/src/vs/workbench/contrib/welcome/page/browser/welcomePage.css b/src/vs/workbench/contrib/welcome/page/browser/welcomePage.css
-index 738ce140c1af76ee0017c59cc883578e966f5348..80833b7023ed5795bb3de303b54ec08d9dab9b94 100644
---- a/src/vs/workbench/contrib/welcome/page/browser/welcomePage.css
-+++ b/src/vs/workbench/contrib/welcome/page/browser/welcomePage.css
-@@ -94,7 +94,7 @@
- }
-
- .monaco-workbench .part.editor > .content .welcomePage .splash .section {
-- margin-bottom: 5em;
-+ margin-bottom: 3em;
- }
-
- .monaco-workbench .part.editor > .content .welcomePage .splash ul {
-diff --git a/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts b/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts
-index 4a61a79fe447e2aa238af568791bff1e0cec4d29..69cc2e4331a3b04d05d79632920f5c5bbfa924e8 100644
---- a/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts
-+++ b/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts
-@@ -328,7 +328,7 @@ class WelcomePage extends Disposable {
-
- const prodName = container.querySelector('.welcomePage .title .caption') as HTMLElement;
- if (prodName) {
-- prodName.textContent = this.productService.nameLong;
-+ prodName.textContent = `code-server v${this.productService.codeServerVersion}`;
- }
-
- recentlyOpened.then(({ workspaces }) => {
-diff --git a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts
-index ed4f26407391bd62219a9f8245a5cd63a7cb7488..92f26d1b082f80475cf76409a4569e948e9e0bd9 100644
---- a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts
-+++ b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts
-@@ -130,6 +130,8 @@ export class SimpleNativeWorkbenchEnvironmentService implements INativeWorkbench
- extensionsPath?: string | undefined;
- extensionsDownloadPath: string = undefined!;
- builtinExtensionsPath: string = undefined!;
-+ extraExtensionPaths: string[] = undefined!;
-+ extraBuiltinExtensionPaths: string[] = undefined!;
-
- driverHandle?: string | undefined;
-
-diff --git a/src/vs/workbench/services/dialogs/browser/dialogService.ts b/src/vs/workbench/services/dialogs/browser/dialogService.ts
-index 85d83f37da179a1e39266cf72a02e971f590308e..0659738b36df1747c9afcabf8d9abf26c890990b 100644
---- a/src/vs/workbench/services/dialogs/browser/dialogService.ts
-+++ b/src/vs/workbench/services/dialogs/browser/dialogService.ts
-@@ -125,11 +125,12 @@ export class DialogService implements IDialogService {
- async about(): Promise {
- const detailString = (useAgo: boolean): string => {
- return nls.localize('aboutDetail',
-- "Version: {0}\nCommit: {1}\nDate: {2}\nBrowser: {3}",
-+ "code-server: v{4}\n VS Code: v{0}\nCommit: {1}\nDate: {2}\nBrowser: {3}",
- this.productService.version || 'Unknown',
- this.productService.commit || 'Unknown',
- this.productService.date ? `${this.productService.date}${useAgo ? ' (' + fromNow(new Date(this.productService.date), true) + ')' : ''}` : 'Unknown',
-- navigator.userAgent
-+ navigator.userAgent,
-+ this.productService.codeServerVersion || 'Unknown',
- );
- };
-
-diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts
-index a8d43045ecc8cbe04b3f8440cff16d42aadbcad0..d051473515e35b331672b780109bd40229153c8c 100644
---- a/src/vs/workbench/services/environment/browser/environmentService.ts
-+++ b/src/vs/workbench/services/environment/browser/environmentService.ts
-@@ -119,8 +119,25 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment
- @memoize
- get logFile(): URI { return joinPath(this.options.logsPath, 'window.log'); }
-
-+ // NOTE@coder: Use the same path in // ../../../../platform/environment/node/environmentService.ts
-+ // and don't use the user data scheme. This solves two problems:
-+ // 1. Extensions running in the browser (like Vim) might use these paths
-+ // directly instead of using the file service and most likely can't write
-+ // to `/User` on disk.
-+ // 2. Settings will be stored in the file system instead of in browser
-+ // storage. Using browser storage makes sharing or seeding settings
-+ // between browsers difficult. We may want to revisit this once/if we get
-+ // settings sync.
- @memoize
-- get userRoamingDataHome(): URI { return URI.file('/User').with({ scheme: Schemas.userData }); }
-+ get userRoamingDataHome(): URI { return joinPath(URI.file(this.userDataPath).with({ scheme: Schemas.vscodeRemote }), 'User'); }
-+ @memoize
-+ get userDataPath(): string {
-+ const dataPath = this.payload?.get('userDataPath');
-+ if (!dataPath) {
-+ throw new Error('userDataPath was not provided to environment service');
-+ }
-+ return dataPath;
-+ }
-
- @memoize
- get settingsResource(): URI { return joinPath(this.userRoamingDataHome, 'settings.json'); }
-@@ -301,7 +318,12 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment
- extensionHostDebugEnvironment.params.port = parseInt(value);
- break;
- case 'enableProposedApi':
-- extensionHostDebugEnvironment.extensionEnabledProposedApi = [];
-+ try {
-+ extensionHostDebugEnvironment.extensionEnabledProposedApi = JSON.parse(value);
-+ } catch (error) {
-+ console.error(error);
-+ extensionHostDebugEnvironment.extensionEnabledProposedApi = [];
-+ }
- break;
- }
- }
-diff --git a/src/vs/workbench/services/extensionManagement/browser/extensionEnablementService.ts b/src/vs/workbench/services/extensionManagement/browser/extensionEnablementService.ts
-index 50d4d812b76f09435fcff8148aac4ceeaeb30873..faacf88fcef119f9f959739656d64a84c8f64cbf 100644
---- a/src/vs/workbench/services/extensionManagement/browser/extensionEnablementService.ts
-+++ b/src/vs/workbench/services/extensionManagement/browser/extensionEnablementService.ts
-@@ -221,7 +221,7 @@ export class ExtensionEnablementService extends Disposable implements IWorkbench
- }
- }
- }
-- return true;
-+ return false; // NOTE@coder: Don't disable anything by extensionKind.
- }
- return false;
- }
-diff --git a/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts b/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts
-index de7e301d3f0c67ce662827f61427a5a7b3616b9f..877ea8e11e6e6d34b9a8fe16287af309e569285e 100644
---- a/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts
-+++ b/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts
-@@ -251,7 +251,9 @@ export class ExtensionManagementService extends Disposable implements IWorkbench
-
- // Install Language pack on all servers
- if (isLanguagePackExtension(manifest)) {
-- servers.push(...this.servers);
-+ // NOTE@coder: It does not appear language packs can be installed on the web
-+ // extension management server at this time. Filter out the web to fix this.
-+ servers.push(...this.servers.filter(s => s !== this.extensionManagementServerService.webExtensionManagementServer));
- } else {
- const server = this.getExtensionManagementServerToInstall(manifest);
- if (server) {
-@@ -320,6 +322,11 @@ export class ExtensionManagementService extends Disposable implements IWorkbench
- return this.extensionManagementServerService.webExtensionManagementServer;
- }
-
-+ // NOTE@coder: Fall back to installing on the remote server.
-+ if (this.extensionManagementServerService.remoteExtensionManagementServer) {
-+ return this.extensionManagementServerService.remoteExtensionManagementServer;
-+ }
-+
- return undefined;
- }
-
-diff --git a/src/vs/workbench/services/extensions/browser/extensionService.ts b/src/vs/workbench/services/extensions/browser/extensionService.ts
-index 1dff19bf177eff24f722b748b79835a653241c4d..01ce9bc00cc39c27e75db006425c359f813a4719 100644
---- a/src/vs/workbench/services/extensions/browser/extensionService.ts
-+++ b/src/vs/workbench/services/extensions/browser/extensionService.ts
-@@ -87,7 +87,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten
- if (code === ExtensionHostExitCode.StartTimeout10s) {
- this._notificationService.prompt(
- Severity.Error,
-- nls.localize('extensionService.startTimeout', "The Web Worker Extension Host did not start in 10s."),
-+ nls.localize('extensionService.startTimeout', 'The Web Worker Extension Host did not start in 10s.'),
- []
- );
- return;
-@@ -177,8 +177,10 @@ export class ExtensionService extends AbstractExtensionService implements IExten
- this._remoteAgentService.getEnvironment(),
- this._remoteAgentService.scanExtensions()
- ]);
-- localExtensions = this._checkEnabledAndProposedAPI(localExtensions);
- remoteExtensions = this._checkEnabledAndProposedAPI(remoteExtensions);
-+ // NOTE@coder: Include remotely hosted extensions that should run locally.
-+ localExtensions = this._checkEnabledAndProposedAPI(localExtensions)
-+ .concat(remoteExtensions.filter(ext => !ext.browser && ext.extensionKind && (ext.extensionKind === 'web' || ext.extensionKind.includes('web'))));
-
- const remoteAgentConnection = this._remoteAgentService.getConnection();
- this._runningLocation = this._runningLocationClassifier.determineRunningLocation(localExtensions, remoteExtensions);
-@@ -188,7 +190,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten
-
- const result = this._registry.deltaExtensions(remoteExtensions.concat(localExtensions), []);
- if (result.removedDueToLooping.length > 0) {
-- this._logOrShowMessage(Severity.Error, nls.localize('looping', "The following extensions contain dependency loops and have been disabled: {0}", result.removedDueToLooping.map(e => `'${e.identifier.value}'`).join(', ')));
-+ this._logOrShowMessage(Severity.Error, nls.localize('looping', 'The following extensions contain dependency loops and have been disabled: {0}', result.removedDueToLooping.map(e => `'${e.identifier.value}'`).join(', ')));
- }
-
- if (remoteEnv && remoteAgentConnection) {
-diff --git a/src/vs/workbench/services/extensions/common/extensionsUtil.ts b/src/vs/workbench/services/extensions/common/extensionsUtil.ts
-index 65e532ee58dfc06ed944846d01b885cb8f260ebc..0b6282fde7ad03c7ea9872a777cbf487253abed1 100644
---- a/src/vs/workbench/services/extensions/common/extensionsUtil.ts
-+++ b/src/vs/workbench/services/extensions/common/extensionsUtil.ts
-@@ -37,7 +37,8 @@ export function canExecuteOnWorkspace(manifest: IExtensionManifest, productServi
-
- export function canExecuteOnWeb(manifest: IExtensionManifest, productService: IProductService, configurationService: IConfigurationService): boolean {
- const extensionKind = getExtensionKind(manifest, productService, configurationService);
-- return extensionKind.some(kind => kind === 'web');
-+ // NOTE@coder: Hardcode vim for now.
-+ return extensionKind.some(kind => kind === 'web') || manifest.name === 'vim';
- }
-
- export function getExtensionKind(manifest: IExtensionManifest, productService: IProductService, configurationService: IConfigurationService): ExtensionKind[] {
-diff --git a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts
-index e39d131fe7b1dd4bd1093fedb8faba8e1fe969e8..5529222b24398100e544045d916b28db278f58a2 100644
---- a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts
-+++ b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts
-@@ -16,11 +16,12 @@ import { IInitData } from 'vs/workbench/api/common/extHost.protocol';
- import { MessageType, createMessageOfType, isMessageOfType, IExtHostSocketMessage, IExtHostReadyMessage, IExtHostReduceGraceTimeMessage, ExtensionHostExitCode } from 'vs/workbench/services/extensions/common/extensionHostProtocol';
- import { ExtensionHostMain, IExitFn } from 'vs/workbench/services/extensions/common/extensionHostMain';
- import { VSBuffer } from 'vs/base/common/buffer';
--import { IURITransformer, URITransformer, IRawURITransformer } from 'vs/base/common/uriIpc';
-+import { IURITransformer, URITransformer } from 'vs/base/common/uriIpc';
- import { exists } from 'vs/base/node/pfs';
- import { realpath } from 'vs/base/node/extpath';
- import { IHostUtils } from 'vs/workbench/api/common/extHostExtensionService';
- import { RunOnceScheduler } from 'vs/base/common/async';
-+import * as proxyAgent from 'vs/base/node/proxy_agent';
-
- import 'vs/workbench/api/common/extHost.common.services';
- import 'vs/workbench/api/node/extHost.node.services';
-@@ -57,12 +58,13 @@ const args = minimist(process.argv.slice(2), {
- const Module = require.__$__nodeRequire('module') as any;
- const originalLoad = Module._load;
-
-- Module._load = function (request: string) {
-+ Module._load = function (request: string, parent: object, isMain: boolean) {
- if (request === 'natives') {
- throw new Error('Either the extension or a NPM dependency is using the "natives" node module which is unsupported as it can cause a crash of the extension host. Click [here](https://go.microsoft.com/fwlink/?linkid=871887) to find out more');
- }
-
-- return originalLoad.apply(this, arguments);
-+ // NOTE@coder: Map node_module.asar requests to regular node_modules.
-+ return originalLoad.apply(this, [request.replace(/node_modules\.asar(\.unpacked)?/, 'node_modules'), parent, isMain]);
- };
- })();
-
-@@ -135,8 +137,11 @@ function _createExtHostProtocol(): Promise {
-
- // Wait for rich client to reconnect
- protocol.onSocketClose(() => {
-- // The socket has closed, let's give the renderer a certain amount of time to reconnect
-- disconnectRunner1.schedule();
-+ // NOTE@coder: Inform the server so we can manage offline
-+ // connections there instead. Our goal is to persist connections
-+ // forever (to a reasonable point) to account for things like
-+ // hibernating overnight.
-+ process.send!({ type: 'VSCODE_EXTHOST_DISCONNECTED' });
- });
- }
- }
-@@ -295,6 +300,7 @@ function connectToRenderer(protocol: IMessagePassingProtocol): Promise {
-+ proxyAgent.monkeyPatch(true);
-
- const protocol = await createExtHostProtocol();
- const renderer = await connectToRenderer(protocol);
-@@ -313,11 +319,9 @@ export async function startExtensionHostProcess(): Promise {
-
- // Attempt to load uri transformer
- let uriTransformer: IURITransformer | null = null;
-- if (initData.remote.authority && args.uriTransformerPath) {
-+ if (initData.remote.authority) {
- try {
-- const rawURITransformerFactory = require.__$__nodeRequire(args.uriTransformerPath);
-- const rawURITransformer = rawURITransformerFactory(initData.remote.authority);
-- uriTransformer = new URITransformer(rawURITransformer);
-+ uriTransformer = new URITransformer(initData.remote.authority);
- } catch (e) {
- console.error(e);
- }
-diff --git a/src/vs/workbench/services/extensions/worker/extensionHostWorkerMain.ts b/src/vs/workbench/services/extensions/worker/extensionHostWorkerMain.ts
-index b39a5cbb9eadbc046144d2e76d26a9b0e950ddaa..3b4cc7274e149ee10dba0dbbb09cf25939091f4b 100644
---- a/src/vs/workbench/services/extensions/worker/extensionHostWorkerMain.ts
-+++ b/src/vs/workbench/services/extensions/worker/extensionHostWorkerMain.ts
-@@ -15,7 +15,11 @@
- require.config({
- baseUrl: monacoBaseUrl,
- catchError: true,
-- createTrustedScriptURL: (value: string) => value
-+ createTrustedScriptURL: (value: string) => value,
-+ paths: {
-+ '@coder/node-browser': `../node_modules/@coder/node-browser/out/client/client.js`,
-+ '@coder/requirefs': `../node_modules/@coder/requirefs/out/requirefs.js`,
-+ }
- });
-
- require(['vs/workbench/services/extensions/worker/extensionHostWorker'], () => { }, err => console.error(err));
-diff --git a/src/vs/workbench/services/localizations/electron-browser/localizationsService.ts b/src/vs/workbench/services/localizations/electron-browser/localizationsService.ts
-index d7aefde89c74bc6096d6e66c45368c8582594efa..9758f3bb96b48603251336e6a64e270ee89744f0 100644
---- a/src/vs/workbench/services/localizations/electron-browser/localizationsService.ts
-+++ b/src/vs/workbench/services/localizations/electron-browser/localizationsService.ts
-@@ -5,8 +5,8 @@
-
- import { createChannelSender } from 'vs/base/parts/ipc/common/ipc';
- import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
--import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
- import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
-+import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
-
- // @ts-ignore: interface is implemented via proxy
- export class LocalizationsService implements ILocalizationsService {
-@@ -14,9 +14,9 @@ export class LocalizationsService implements ILocalizationsService {
- declare readonly _serviceBrand: undefined;
-
- constructor(
-- @ISharedProcessService sharedProcessService: ISharedProcessService,
-+ @IRemoteAgentService remoteAgentService: IRemoteAgentService,
- ) {
-- return createChannelSender(sharedProcessService.getChannel('localizations'));
-+ return createChannelSender(remoteAgentService.getConnection()!.getChannel('localizations'));
- }
- }
-
-diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts
-index 509f8ac8ce3a689386e439302a53c27e4fdfcef7..2bf9a737bd0dbfa1e604acfc890be45823f02ebe 100644
---- a/src/vs/workbench/workbench.web.main.ts
-+++ b/src/vs/workbench/workbench.web.main.ts
-@@ -35,7 +35,8 @@ import 'vs/workbench/services/textfile/browser/browserTextFileService';
- import 'vs/workbench/services/keybinding/browser/keymapService';
- import 'vs/workbench/services/extensions/browser/extensionService';
- import 'vs/workbench/services/extensionManagement/common/extensionManagementServerService';
--import 'vs/workbench/services/telemetry/browser/telemetryService';
-+// NOTE@coder: We send it all to the server side to be processed there instead.
-+// import 'vs/workbench/services/telemetry/browser/telemetryService';
- import 'vs/workbench/services/configurationResolver/browser/configurationResolverService';
- import 'vs/workbench/services/credentials/browser/credentialsService';
- import 'vs/workbench/services/url/browser/urlService';
-diff --git a/yarn.lock b/yarn.lock
-index ff358cb6a10984868ed5a5aed5729ac6eb8ebeb7..c73be6d8e9f9b213aeee2b4c22b53fc5d4184c56 100644
---- a/yarn.lock
-+++ b/yarn.lock
-@@ -140,6 +140,23 @@
- lodash "^4.17.13"
- to-fast-properties "^2.0.0"
-
-+"@coder/logger@1.1.16":
-+ version "1.1.16"
-+ resolved "https://registry.yarnpkg.com/@coder/logger/-/logger-1.1.16.tgz#ee5b1b188f680733f35c11b065bbd139d618c1e1"
-+ integrity sha512-X6VB1++IkosYY6amRAiMvuvCf12NA4+ooX+gOuu5bJIkdjmh4Lz7QpJcWRdgxesvo1msriDDr9E/sDbIWf6vsQ==
-+
-+"@coder/node-browser@^1.0.8":
-+ version "1.0.8"
-+ resolved "https://registry.yarnpkg.com/@coder/node-browser/-/node-browser-1.0.8.tgz#c22f581b089ad7d95ad1362fd351c57b7fbc6e70"
-+ integrity sha512-NLF9sYMRCN9WK1C224pHax1Cay3qKypg25BhVg7VfNbo3Cpa3daata8RF/rT8JK3lPsu8PmFgDRQjzGC9X1Lrw==
-+
-+"@coder/requirefs@^1.1.5":
-+ version "1.1.5"
-+ resolved "https://registry.yarnpkg.com/@coder/requirefs/-/requirefs-1.1.5.tgz#259db370d563a79a96fb150bc9d69c7db6edc9fb"
-+ integrity sha512-3jB47OFCql9+9FI6Vc4YX0cfFnG5rxBfrZUH45S4XYtYGOz+/Xl4h4d2iMk50b7veHkeSWGlB4VHC3UZ16zuYQ==
-+ optionalDependencies:
-+ jszip "2.6.0"
-+
- "@electron/get@^1.0.1":
- version "1.7.2"
- resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.7.2.tgz#286436a9fb56ff1a1fcdf0e80131fd65f4d1e0fd"
-@@ -172,6 +189,11 @@
- dependencies:
- defer-to-connect "^1.0.1"
-
-+"@tootallnate/once@1":
-+ version "1.1.2"
-+ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
-+ integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
-+
- "@types/applicationinsights@0.20.0":
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/@types/applicationinsights/-/applicationinsights-0.20.0.tgz#fa7b36dc954f635fa9037cad27c378446b1048fb"
-@@ -634,6 +656,13 @@ agent-base@^4.3.0:
- dependencies:
- es6-promisify "^5.0.0"
-
-+agent-base@^6.0.0:
-+ version "6.0.2"
-+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
-+ integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
-+ dependencies:
-+ debug "4"
-+
- agent-base@~4.2.1:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9"
-@@ -1045,6 +1074,13 @@ assign-symbols@^1.0.0:
- resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
- integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
-
-+ast-types@^0.13.2:
-+ version "0.13.4"
-+ resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.4.tgz#ee0d77b343263965ecc3fb62da16e7222b2b6782"
-+ integrity sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==
-+ dependencies:
-+ tslib "^2.0.1"
-+
- astral-regex@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
-@@ -1464,6 +1500,11 @@ builtin-status-codes@^3.0.0:
- resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
- integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=
-
-+bytes@3.1.0:
-+ version "3.1.0"
-+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
-+ integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
-+
- cacache@^10.0.4:
- version "10.0.4"
- resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.4.tgz#6452367999eff9d4188aefd9a14e9d7c6a263460"
-@@ -2365,6 +2406,11 @@ dashdash@^1.12.0:
- dependencies:
- assert-plus "^1.0.0"
-
-+data-uri-to-buffer@3:
-+ version "3.0.1"
-+ resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636"
-+ integrity sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==
-+
- date-fns@^2.0.1:
- version "2.14.0"
- resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.14.0.tgz#359a87a265bb34ef2e38f93ecf63ac453f9bc7ba"
-@@ -2513,6 +2559,15 @@ defined@^1.0.0:
- resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
- integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=
-
-+degenerator@^2.2.0:
-+ version "2.2.0"
-+ resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-2.2.0.tgz#49e98c11fa0293c5b26edfbb52f15729afcdb254"
-+ integrity sha512-aiQcQowF01RxFI4ZLFMpzyotbQonhNpBao6dkI8JPk5a+hmSjR5ErHp2CQySmQe8os3VBqLCIh87nDBgZXvsmg==
-+ dependencies:
-+ ast-types "^0.13.2"
-+ escodegen "^1.8.1"
-+ esprima "^4.0.0"
-+
- del@^2.0.2:
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8"
-@@ -2546,6 +2601,11 @@ denodeify@^1.2.1:
- resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631"
- integrity sha1-OjYof1A05pnnV3kBBSwubJQlFjE=
-
-+depd@~1.1.2:
-+ version "1.1.2"
-+ resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
-+ integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
-+
- des.js@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc"
-@@ -2931,6 +2991,18 @@ escape-string-regexp@^2.0.0:
- resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
- integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
-
-+escodegen@^1.8.1:
-+ version "1.14.3"
-+ resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503"
-+ integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==
-+ dependencies:
-+ esprima "^4.0.1"
-+ estraverse "^4.2.0"
-+ esutils "^2.0.2"
-+ optionator "^0.8.1"
-+ optionalDependencies:
-+ source-map "~0.6.1"
-+
- eslint-plugin-jsdoc@^19.1.0:
- version "19.1.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-19.1.0.tgz#fcc17f0378fdd6ee1c847a79b7211745cb05d014"
-@@ -3126,6 +3198,11 @@ esprima@^4.0.0:
- resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804"
- integrity sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==
-
-+esprima@^4.0.1:
-+ version "4.0.1"
-+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
-+ integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
-+
- esquery@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708"
-@@ -3146,6 +3223,11 @@ estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1:
- resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
- integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=
-
-+estraverse@^4.2.0:
-+ version "4.3.0"
-+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
-+ integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
-+
- esutils@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
-@@ -3435,6 +3517,11 @@ file-uri-to-path@1.0.0:
- resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
- integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
-
-+file-uri-to-path@2:
-+ version "2.0.0"
-+ resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz#7b415aeba227d575851e0a5b0c640d7656403fba"
-+ integrity sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==
-+
- filename-regex@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.0.tgz#996e3e80479b98b9897f15a8a58b3d084e926775"
-@@ -3746,6 +3833,14 @@ fstream@^1.0.2:
- mkdirp ">=0.5 0"
- rimraf "2"
-
-+ftp@^0.3.10:
-+ version "0.3.10"
-+ resolved "https://registry.yarnpkg.com/ftp/-/ftp-0.3.10.tgz#9197d861ad8142f3e63d5a83bfe4c59f7330885d"
-+ integrity sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=
-+ dependencies:
-+ readable-stream "1.1.x"
-+ xregexp "2.0.0"
-+
- function-bind@^1.0.2, function-bind@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
-@@ -3799,6 +3894,18 @@ get-stream@^5.1.0:
- dependencies:
- pump "^3.0.0"
-
-+get-uri@3:
-+ version "3.0.2"
-+ resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-3.0.2.tgz#f0ef1356faabc70e1f9404fa3b66b2ba9bfc725c"
-+ integrity sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==
-+ dependencies:
-+ "@tootallnate/once" "1"
-+ data-uri-to-buffer "3"
-+ debug "4"
-+ file-uri-to-path "2"
-+ fs-extra "^8.1.0"
-+ ftp "^0.3.10"
-+
- get-value@^2.0.3, get-value@^2.0.6:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
-@@ -4541,6 +4648,17 @@ http-cache-semantics@^4.0.0:
- resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz#495704773277eeef6e43f9ab2c2c7d259dda25c5"
- integrity sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew==
-
-+http-errors@1.7.3:
-+ version "1.7.3"
-+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
-+ integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==
-+ dependencies:
-+ depd "~1.1.2"
-+ inherits "2.0.4"
-+ setprototypeof "1.1.1"
-+ statuses ">= 1.5.0 < 2"
-+ toidentifier "1.0.0"
-+
- http-proxy-agent@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
-@@ -4549,6 +4667,15 @@ http-proxy-agent@^2.1.0:
- agent-base "4"
- debug "3.1.0"
-
-+http-proxy-agent@^4.0.0, http-proxy-agent@^4.0.1:
-+ version "4.0.1"
-+ resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a"
-+ integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==
-+ dependencies:
-+ "@tootallnate/once" "1"
-+ agent-base "6"
-+ debug "4"
-+
- http-signature@~1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
-@@ -4563,6 +4690,14 @@ https-browserify@^1.0.0:
- resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
- integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
-
-+https-proxy-agent@5, https-proxy-agent@^5.0.0:
-+ version "5.0.0"
-+ resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
-+ integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==
-+ dependencies:
-+ agent-base "6"
-+ debug "4"
-+
- https-proxy-agent@^2.2.3:
- version "2.2.4"
- resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
-@@ -4579,14 +4714,6 @@ https-proxy-agent@^4.0.0:
- agent-base "5"
- debug "4"
-
--https-proxy-agent@^5.0.0:
-- version "5.0.0"
-- resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
-- integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==
-- dependencies:
-- agent-base "6"
-- debug "4"
--
- husky@^0.13.1:
- version "0.13.4"
- resolved "https://registry.yarnpkg.com/husky/-/husky-0.13.4.tgz#48785c5028de3452a51c48c12c4f94b2124a1407"
-@@ -4602,18 +4729,18 @@ iconv-lite-umd@0.6.8:
- resolved "https://registry.yarnpkg.com/iconv-lite-umd/-/iconv-lite-umd-0.6.8.tgz#5ad310ec126b260621471a2d586f7f37b9958ec0"
- integrity sha512-zvXJ5gSwMC9JD3wDzH8CoZGc1pbiJn12Tqjk8BXYCnYz3hYL5GRjHW8LEykjXhV9WgNGI4rgpgHcbIiBfrRq6A==
-
--iconv-lite@^0.4.19:
-- version "0.4.19"
-- resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
-- integrity sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==
--
--iconv-lite@^0.4.24:
-+iconv-lite@0.4.24, iconv-lite@^0.4.24:
- version "0.4.24"
- resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
- integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
- dependencies:
- safer-buffer ">= 2.1.2 < 3"
-
-+iconv-lite@^0.4.19:
-+ version "0.4.19"
-+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
-+ integrity sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==
-+
- iconv-lite@^0.4.4:
- version "0.4.23"
- resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
-@@ -4704,7 +4831,7 @@ inherits@2.0.1:
- resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
- integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=
-
--inherits@^2.0.4:
-+inherits@2.0.4, inherits@^2.0.4:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
- integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
-@@ -5403,6 +5530,13 @@ jsprim@^1.2.2:
- json-schema "0.2.3"
- verror "1.10.0"
-
-+jszip@2.6.0:
-+ version "2.6.0"
-+ resolved "https://registry.yarnpkg.com/jszip/-/jszip-2.6.0.tgz#7fb3e9c2f11c8a9840612db5dabbc8cf3a7534b7"
-+ integrity sha1-f7PpwvEciphAYS212rvIzzp1NLc=
-+ dependencies:
-+ pako "~1.0.0"
-+
- just-debounce@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.0.0.tgz#87fccfaeffc0b68cd19d55f6722943f929ea35ea"
-@@ -5983,26 +6117,11 @@ minimatch@0.3:
- dependencies:
- brace-expansion "^1.1.7"
-
--minimist@0.0.8:
-- version "0.0.8"
-- resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
-- integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
--
--minimist@^1.2.0:
-- version "1.2.0"
-- resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
-- integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
--
--minimist@^1.2.5:
-+minimist@0.0.8, minimist@^1.2.0, minimist@^1.2.5, minimist@~0.0.1:
- version "1.2.5"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
- integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
-
--minimist@~0.0.1:
-- version "0.0.10"
-- resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
-- integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=
--
- minipass@^2.2.1, minipass@^2.3.3:
- version "2.3.3"
- resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.3.tgz#a7dcc8b7b833f5d368759cce544dccb55f50f233"
-@@ -6232,6 +6351,11 @@ neo-async@^2.6.1:
- resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c"
- integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==
-
-+netmask@^1.0.6:
-+ version "1.0.6"
-+ resolved "https://registry.yarnpkg.com/netmask/-/netmask-1.0.6.tgz#20297e89d86f6f6400f250d9f4f6b4c1945fcd35"
-+ integrity sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=
-+
- nice-try@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4"
-@@ -6581,6 +6705,18 @@ optimist@^0.6.1:
- minimist "~0.0.1"
- wordwrap "~0.0.2"
-
-+optionator@^0.8.1, optionator@^0.8.3:
-+ version "0.8.3"
-+ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
-+ integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
-+ dependencies:
-+ deep-is "~0.1.3"
-+ fast-levenshtein "~2.0.6"
-+ levn "~0.3.0"
-+ prelude-ls "~1.1.2"
-+ type-check "~0.3.2"
-+ word-wrap "~1.2.3"
-+
- optionator@^0.8.2:
- version "0.8.2"
- resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
-@@ -6593,18 +6729,6 @@ optionator@^0.8.2:
- type-check "~0.3.2"
- wordwrap "~1.0.0"
-
--optionator@^0.8.3:
-- version "0.8.3"
-- resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
-- integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
-- dependencies:
-- deep-is "~0.1.3"
-- fast-levenshtein "~2.0.6"
-- levn "~0.3.0"
-- prelude-ls "~1.1.2"
-- type-check "~0.3.2"
-- word-wrap "~1.2.3"
--
- ordered-read-streams@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b"
-@@ -6744,6 +6868,35 @@ p-try@^2.0.0:
- resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1"
- integrity sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==
-
-+pac-proxy-agent@^4.1.0:
-+ version "4.1.0"
-+ resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-4.1.0.tgz#66883eeabadc915fc5e95457324cb0f0ac78defb"
-+ integrity sha512-ejNgYm2HTXSIYX9eFlkvqFp8hyJ374uDf0Zq5YUAifiSh1D6fo+iBivQZirGvVv8dCYUsLhmLBRhlAYvBKI5+Q==
-+ dependencies:
-+ "@tootallnate/once" "1"
-+ agent-base "6"
-+ debug "4"
-+ get-uri "3"
-+ http-proxy-agent "^4.0.1"
-+ https-proxy-agent "5"
-+ pac-resolver "^4.1.0"
-+ raw-body "^2.2.0"
-+ socks-proxy-agent "5"
-+
-+pac-resolver@^4.1.0:
-+ version "4.1.0"
-+ resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-4.1.0.tgz#4b12e7d096b255a3b84e53f6831f32e9c7e5fe95"
-+ integrity sha512-d6lf2IrZJJ7ooVHr7BfwSjRO1yKSJMaiiWYSHcrxSIUtZrCa4KKGwcztdkZ/E9LFleJfjoi1yl+XLR7AX24nbQ==
-+ dependencies:
-+ degenerator "^2.2.0"
-+ ip "^1.1.5"
-+ netmask "^1.0.6"
-+
-+pako@~1.0.0:
-+ version "1.0.11"
-+ resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
-+ integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
-+
- pako@~1.0.5:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258"
-@@ -7439,7 +7592,21 @@ proto-list@~1.2.1:
- resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
- integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=
-
--proxy-from-env@^1.1.0:
-+proxy-agent@^4.0.0:
-+ version "4.0.0"
-+ resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-4.0.0.tgz#a92976af3fbc7d846f2e850e2ac5ac6ca3fb74c7"
-+ integrity sha512-8P0Y2SkwvKjiGU1IkEfYuTteioMIDFxPL4/j49zzt5Mz3pG1KO+mIrDG1qH0PQUHTTczjwGcYl+EzfXiFj5vUQ==
-+ dependencies:
-+ agent-base "^6.0.0"
-+ debug "4"
-+ http-proxy-agent "^4.0.0"
-+ https-proxy-agent "^5.0.0"
-+ lru-cache "^5.1.1"
-+ pac-proxy-agent "^4.1.0"
-+ proxy-from-env "^1.0.0"
-+ socks-proxy-agent "^5.0.0"
-+
-+proxy-from-env@^1.0.0, proxy-from-env@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
- integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
-@@ -7607,6 +7774,16 @@ randomfill@^1.0.3:
- randombytes "^2.0.5"
- safe-buffer "^5.1.0"
-
-+raw-body@^2.2.0:
-+ version "2.4.1"
-+ resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c"
-+ integrity sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==
-+ dependencies:
-+ bytes "3.1.0"
-+ http-errors "1.7.3"
-+ iconv-lite "0.4.24"
-+ unpipe "1.0.0"
-+
- rc@^1.2.7:
- version "1.2.8"
- resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
-@@ -7673,6 +7850,16 @@ read@^1.0.7:
- string_decoder "~1.1.1"
- util-deprecate "~1.0.1"
-
-+readable-stream@1.1.x:
-+ version "1.1.14"
-+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
-+ integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk=
-+ dependencies:
-+ core-util-is "~1.0.0"
-+ inherits "~2.0.1"
-+ isarray "0.0.1"
-+ string_decoder "~0.10.x"
-+
- "readable-stream@2 || 3":
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.1.1.tgz#ed6bbc6c5ba58b090039ff18ce670515795aeb06"
-@@ -8296,6 +8483,11 @@ setimmediate@^1.0.4:
- resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
- integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
-
-+setprototypeof@1.1.1:
-+ version "1.1.1"
-+ resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
-+ integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
-+
- sha.js@^2.4.0, sha.js@^2.4.8:
- version "2.4.11"
- resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
-@@ -8374,6 +8566,11 @@ smart-buffer@4.0.2:
- resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.2.tgz#5207858c3815cc69110703c6b94e46c15634395d"
- integrity sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==
-
-+smart-buffer@^4.1.0:
-+ version "4.1.0"
-+ resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.1.0.tgz#91605c25d91652f4661ea69ccf45f1b331ca21ba"
-+ integrity sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==
-+
- snapdragon-node@^2.0.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
-@@ -8411,6 +8608,15 @@ sntp@2.x.x:
- dependencies:
- hoek "4.x.x"
-
-+socks-proxy-agent@5, socks-proxy-agent@^5.0.0:
-+ version "5.0.0"
-+ resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-5.0.0.tgz#7c0f364e7b1cf4a7a437e71253bed72e9004be60"
-+ integrity sha512-lEpa1zsWCChxiynk+lCycKuC502RxDWLKJZoIhnxrWNjLSDGYRFflHA1/228VkRcnv9TIb8w98derGbpKxJRgA==
-+ dependencies:
-+ agent-base "6"
-+ debug "4"
-+ socks "^2.3.3"
-+
- socks-proxy-agent@^4.0.1:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz#3c8991f3145b2799e70e11bd5fbc8b1963116386"
-@@ -8419,6 +8625,14 @@ socks-proxy-agent@^4.0.1:
- agent-base "~4.2.1"
- socks "~2.3.2"
-
-+socks@^2.3.3:
-+ version "2.5.1"
-+ resolved "https://registry.yarnpkg.com/socks/-/socks-2.5.1.tgz#7720640b6b5ec9a07d556419203baa3f0596df5f"
-+ integrity sha512-oZCsJJxapULAYJaEYBSzMcz8m3jqgGrHaGhkmU/o/PQfFWYWxkAaA0UMGImb6s6tEXfKi959X6VJjMMQ3P6TTQ==
-+ dependencies:
-+ ip "^1.1.5"
-+ smart-buffer "^4.1.0"
-+
- socks@~2.3.2:
- version "2.3.2"
- resolved "https://registry.yarnpkg.com/socks/-/socks-2.3.2.tgz#ade388e9e6d87fdb11649c15746c578922a5883e"
-@@ -8612,6 +8826,11 @@ static-extend@^0.1.1:
- define-property "^0.2.5"
- object-copy "^0.1.0"
-
-+"statuses@>= 1.5.0 < 2":
-+ version "1.5.0"
-+ resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
-+ integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
-+
- stream-browserify@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db"
-@@ -9170,6 +9389,11 @@ to-through@^2.0.0:
- dependencies:
- through2 "^2.0.3"
-
-+toidentifier@1.0.0:
-+ version "1.0.0"
-+ resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
-+ integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
-+
- tough-cookie@~2.3.3:
- version "2.3.3"
- resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561"
-@@ -9219,6 +9443,11 @@ tslib@^1.8.1, tslib@^1.9.0:
- resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
- integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==
-
-+tslib@^2.0.1:
-+ version "2.0.3"
-+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c"
-+ integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==
-+
- tsutils@^3.17.1:
- version "3.17.1"
- resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"
-@@ -9397,6 +9626,11 @@ universalify@^0.1.0:
- resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
- integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
-
-+unpipe@1.0.0:
-+ version "1.0.0"
-+ resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
-+ integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
-+
- unset-value@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
-@@ -10049,6 +10283,11 @@ xmldom@0.1.x:
- resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc"
- integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=
-
-+xregexp@2.0.0:
-+ version "2.0.0"
-+ resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943"
-+ integrity sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=
-+
- "xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
diff --git a/ci/dev/vscode.sh b/ci/dev/vscode.sh
deleted file mode 100755
index 6c508747aa6f..000000000000
--- a/ci/dev/vscode.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-# 1. Ensures VS Code is cloned.
-# 2. Patches it.
-# 3. Installs it.
-main() {
- cd "$(dirname "$0")/../.."
-
- git submodule update --init
-
- # If the patch fails to apply, then it's likely already applied
- yarn vscode:patch &> /dev/null || true
-
- (
- cd lib/vscode
- # Install VS Code dependencies.
- yarn ${CI+--frozen-lockfile}
- )
-}
-
-main "$@"
diff --git a/ci/dev/watch.ts b/ci/dev/watch.ts
index 646da328b3f8..e48489ce69dc 100644
--- a/ci/dev/watch.ts
+++ b/ci/dev/watch.ts
@@ -1,193 +1,142 @@
-import * as cp from "child_process"
-import Bundler from "parcel-bundler"
+import { spawn, ChildProcess } from "child_process"
import * as path from "path"
-
-async function main(): Promise {
- try {
- const watcher = new Watcher()
- await watcher.watch()
- } catch (error) {
- console.error(error.message)
- process.exit(1)
- }
+import { onLine, OnLineCallback } from "../../src/node/util"
+
+interface DevelopmentCompilers {
+ [key: string]: ChildProcess | undefined
+ vscode: ChildProcess
+ vscodeWebExtensions: ChildProcess
+ codeServer: ChildProcess
+ plugins: ChildProcess | undefined
}
class Watcher {
- private readonly rootPath = path.resolve(__dirname, "../..")
- private readonly vscodeSourcePath = path.join(this.rootPath, "lib/vscode")
+ private rootPath = path.resolve(process.cwd())
+ private readonly paths = {
+ /** Path to uncompiled VS Code source. */
+ vscodeDir: path.join(this.rootPath, "lib/vscode"),
+ pluginDir: process.env.PLUGIN_DIR,
+ }
+
+ //#region Web Server
+
+ /** Development web server. */
+ private webServer: ChildProcess | undefined
- private static log(message: string, skipNewline = false): void {
- process.stdout.write(message)
- if (!skipNewline) {
- process.stdout.write("\n")
+ private reloadWebServer = (): void => {
+ if (this.webServer) {
+ this.webServer.kill()
}
+
+ // Pass CLI args, save for `node` and the initial script name.
+ const args = process.argv.slice(2)
+ this.webServer = spawn("node", [path.join(this.rootPath, "out/node/entry.js"), ...args])
+ onLine(this.webServer, (line) => console.log("[code-server]", line))
+ const { pid } = this.webServer
+
+ this.webServer.on("exit", () => console.log("[code-server]", `Web process ${pid} exited`))
+
+ console.log("\n[code-server]", `Spawned web server process ${pid}`)
}
- public async watch(): Promise {
- let server: cp.ChildProcess | undefined
- const restartServer = (): void => {
- if (server) {
- server.kill()
- }
- const s = cp.fork(path.join(this.rootPath, "out/node/entry.js"), process.argv.slice(2))
- console.log(`[server] spawned process ${s.pid}`)
- s.on("exit", () => console.log(`[server] process ${s.pid} exited`))
- server = s
+ //#endregion
+
+ //#region Compilers
+
+ private readonly compilers: DevelopmentCompilers = {
+ codeServer: spawn("tsc", ["--watch", "--pretty", "--preserveWatchOutput"], { cwd: this.rootPath }),
+ vscode: spawn("npm", ["run", "watch"], { cwd: this.paths.vscodeDir }),
+ vscodeWebExtensions: spawn("npm", ["run", "watch-web"], { cwd: this.paths.vscodeDir }),
+ plugins: this.paths.pluginDir
+ ? spawn("npm", ["run", "build", "--watch"], { cwd: this.paths.pluginDir })
+ : undefined,
+ }
+
+ public async initialize(): Promise {
+ for (const event of ["SIGINT", "SIGTERM"]) {
+ process.on(event, () => this.dispose(0))
}
- const vscode = cp.spawn("yarn", ["watch"], { cwd: this.vscodeSourcePath })
- const tsc = cp.spawn("tsc", ["--watch", "--pretty", "--preserveWatchOutput"], { cwd: this.rootPath })
- const plugin = process.env.PLUGIN_DIR
- ? cp.spawn("yarn", ["build", "--watch"], { cwd: process.env.PLUGIN_DIR })
- : undefined
- const bundler = this.createBundler()
-
- const cleanup = (code?: number | null): void => {
- Watcher.log("killing vs code watcher")
- vscode.removeAllListeners()
- vscode.kill()
-
- Watcher.log("killing tsc")
- tsc.removeAllListeners()
- tsc.kill()
-
- if (plugin) {
- Watcher.log("killing plugin")
- plugin.removeAllListeners()
- plugin.kill()
- }
+ for (const [processName, devProcess] of Object.entries(this.compilers)) {
+ if (!devProcess) continue
- if (server) {
- Watcher.log("killing server")
- server.removeAllListeners()
- server.kill()
+ devProcess.on("exit", (code) => {
+ console.log(`[${processName}]`, "Terminated unexpectedly")
+ this.dispose(code)
+ })
+
+ if (devProcess.stderr) {
+ devProcess.stderr.on("data", (d: string | Uint8Array) => process.stderr.write(d))
}
+ }
+
+ onLine(this.compilers.vscode, this.parseVSCodeLine)
+ onLine(this.compilers.codeServer, this.parseCodeServerLine)
- Watcher.log("killing bundler")
- process.exit(code || 0)
+ if (this.compilers.plugins) {
+ onLine(this.compilers.plugins, this.parsePluginLine)
}
+ }
- process.on("SIGINT", () => cleanup())
- process.on("SIGTERM", () => cleanup())
-
- vscode.on("exit", (code) => {
- Watcher.log("vs code watcher terminated unexpectedly")
- cleanup(code)
- })
- tsc.on("exit", (code) => {
- Watcher.log("tsc terminated unexpectedly")
- cleanup(code)
- })
- if (plugin) {
- plugin.on("exit", (code) => {
- Watcher.log("plugin terminated unexpectedly")
- cleanup(code)
- })
+ //#endregion
+
+ //#region Line Parsers
+
+ private parseVSCodeLine: OnLineCallback = (strippedLine, originalLine) => {
+ if (!strippedLine.length) return
+
+ console.log("[Code OSS]", originalLine)
+
+ if (strippedLine.includes("Finished compilation with")) {
+ console.log("[Code OSS] ✨ Finished compiling! ✨", "(Refresh your web browser ♻️)")
+ this.reloadWebServer()
}
- const bundle = bundler.bundle().catch(() => {
- Watcher.log("parcel watcher terminated unexpectedly")
- cleanup(1)
- })
- bundler.on("buildEnd", () => {
- console.log("[parcel] bundled")
- })
- bundler.on("buildError", (error) => {
- console.error("[parcel]", error)
- })
-
- vscode.stderr.on("data", (d) => process.stderr.write(d))
- tsc.stderr.on("data", (d) => process.stderr.write(d))
- if (plugin) {
- plugin.stderr.on("data", (d) => process.stderr.write(d))
+ }
+
+ private parseCodeServerLine: OnLineCallback = (strippedLine, originalLine) => {
+ if (!strippedLine.length) return
+
+ console.log("[Compiler][code-server]", originalLine)
+
+ if (strippedLine.includes("Watching for file changes")) {
+ console.log("[Compiler][code-server]", "Finished compiling!", "(Refresh your web browser ♻️)")
+ this.reloadWebServer()
}
+ }
- // From https://github.com/chalk/ansi-regex
- const pattern = [
- "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)",
- "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))",
- ].join("|")
- const re = new RegExp(pattern, "g")
-
- /**
- * Split stdout on newlines and strip ANSI codes.
- */
- const onLine = (proc: cp.ChildProcess, callback: (strippedLine: string, originalLine: string) => void): void => {
- let buffer = ""
- if (!proc.stdout) {
- throw new Error("no stdout")
- }
- proc.stdout.setEncoding("utf8")
- proc.stdout.on("data", (d) => {
- const data = buffer + d
- const split = data.split("\n")
- const last = split.length - 1
-
- for (let i = 0; i < last; ++i) {
- callback(split[i].replace(re, ""), split[i])
- }
-
- // The last item will either be an empty string (the data ended with a
- // newline) or a partial line (did not end with a newline) and we must
- // wait to parse it until we get a full line.
- buffer = split[last]
- })
+ private parsePluginLine: OnLineCallback = (strippedLine, originalLine) => {
+ if (!strippedLine.length) return
+
+ console.log("[Compiler][Plugin]", originalLine)
+
+ if (strippedLine.includes("Watching for file changes...")) {
+ this.reloadWebServer()
}
+ }
- let startingVscode = false
- let startedVscode = false
- onLine(vscode, (line, original) => {
- console.log("[vscode]", original)
- // Wait for watch-client since "Finished compilation" will appear multiple
- // times before the client starts building.
- if (!startingVscode && line.includes("Starting watch-client")) {
- startingVscode = true
- } else if (startingVscode && line.includes("Finished compilation")) {
- if (startedVscode) {
- bundle.then(restartServer)
- }
- startedVscode = true
- }
- })
+ //#endregion
- onLine(tsc, (line, original) => {
- // tsc outputs blank lines; skip them.
- if (line !== "") {
- console.log("[tsc]", original)
- }
- if (line.includes("Watching for file changes")) {
- bundle.then(restartServer)
- }
- })
-
- if (plugin) {
- onLine(plugin, (line, original) => {
- // tsc outputs blank lines; skip them.
- if (line !== "") {
- console.log("[plugin]", original)
- }
- if (line.includes("Watching for file changes")) {
- bundle.then(restartServer)
- }
- })
+ //#region Utilities
+
+ private dispose(code: number | null): void {
+ for (const [processName, devProcess] of Object.entries(this.compilers)) {
+ console.log(`[${processName}]`, "Killing...\n")
+ devProcess?.removeAllListeners()
+ devProcess?.kill()
}
+ process.exit(typeof code === "number" ? code : 0)
}
- private createBundler(out = "dist"): Bundler {
- return new Bundler(
- [
- path.join(this.rootPath, "src/browser/register.ts"),
- path.join(this.rootPath, "src/browser/serviceWorker.ts"),
- path.join(this.rootPath, "src/browser/pages/login.ts"),
- path.join(this.rootPath, "src/browser/pages/vscode.ts"),
- ],
- {
- outDir: path.join(this.rootPath, out),
- cacheDir: path.join(this.rootPath, ".cache"),
- minify: !!process.env.MINIFY,
- logLevel: 1,
- publicUrl: ".",
- },
- )
+ //#endregion
+}
+
+async function main(): Promise {
+ try {
+ const watcher = new Watcher()
+ await watcher.initialize()
+ } catch (error: any) {
+ console.error(error.message)
+ process.exit(1)
}
}
diff --git a/ci/helm-chart/Chart.yaml b/ci/helm-chart/Chart.yaml
index 94bf92a2868c..99c540e33719 100644
--- a/ci/helm-chart/Chart.yaml
+++ b/ci/helm-chart/Chart.yaml
@@ -1,6 +1,6 @@
apiVersion: v2
name: code-server
-description: A Helm chart for cdr/code-server
+description: A Helm chart for coder/code-server
# A chart can be either an 'application' or a 'library' chart.
#
@@ -15,9 +15,9 @@ type: application
# 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.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
-version: 1.0.3
+version: 3.48.0
# 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
# follow Semantic Versioning. They should reflect the version the application is using.
-appVersion: 3.7.4
+appVersion: 4.133.0
diff --git a/ci/helm-chart/README.md b/ci/helm-chart/README.md
deleted file mode 100644
index f8547725ae2c..000000000000
--- a/ci/helm-chart/README.md
+++ /dev/null
@@ -1,117 +0,0 @@
-# code-server
-
-  
-
-[code-server](https://github.com/cdr/code-server) code-server is VS Code running
-on a remote server, accessible through the browser.
-
-This chart is community maintained by [@Matthew-Beckett](https://github.com/Matthew-Beckett) and [@alexgorbatchev](https://github.com/alexgorbatchev)
-
-## TL;DR;
-
-```console
-$ git clone https://github.com/cdr/code-server
-$ cd code-server
-$ helm upgrade --install code-server ci/helm-chart
-```
-
-## Introduction
-
-This chart bootstraps a code-server deployment on a
-[Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh)
-package manager.
-
-## Prerequisites
-
- - Kubernetes 1.6+
-
-## Installing the Chart
-
-To install the chart with the release name `code-server`:
-
-```console
-$ git clone https://github.com/cdr/code-server
-$ cd code-server
-$ helm upgrade --install code-server ci/helm-chart
-```
-
-The command deploys code-server on the Kubernetes cluster in the default
-configuration. The [configuration](#configuration) section lists the parameters
-that can be configured during installation.
-
-> **Tip**: List all releases using `helm list`
-
-## Uninstalling the Chart
-
-To uninstall/delete the `code-server` deployment:
-
-```console
-$ helm delete code-server
-```
-
-The command removes all the Kubernetes components associated with the chart and
-deletes the release.
-
-## Configuration
-
-The following table lists the configurable parameters of the code-server chart
-and their default values.
-
-## Values
-
-| Key | Type | Default | Description |
-|-----|------|---------|-------------|
-| affinity | object | `{}` | |
-| extraArgs | list | `[]` | |
-| extraConfigmapMounts | list | `[]` | |
-| extraContainers | string | `""` | |
-| extraSecretMounts | list | `[]` | |
-| extraVars | list | `[]` | |
-| extraVolumeMounts | list | `[]` | |
-| fullnameOverride | string | `""` | |
-| hostnameOverride | string | `""` | |
-| image.pullPolicy | string | `"Always"` | |
-| image.repository | string | `"codercom/code-server"` | |
-| image.tag | string | `"3.7.4"` | |
-| imagePullSecrets | list | `[]` | |
-| ingress.enabled | bool | `false` | |
-| nameOverride | string | `""` | |
-| nodeSelector | object | `{}` | |
-| persistence.accessMode | string | `"ReadWriteOnce"` | |
-| persistence.annotations | object | `{}` | |
-| persistence.enabled | bool | `true` | |
-| persistence.size | string | `"1Gi"` | |
-| podAnnotations | object | `{}` | |
-| podSecurityContext | object | `{}` | |
-| replicaCount | int | `1` | |
-| resources | object | `{}` | |
-| securityContext.enabled | bool | `true` | |
-| securityContext.fsGroup | int | `1000` | |
-| securityContext.runAsUser | int | `1000` | |
-| service.port | int | `8443` | |
-| service.type | string | `"ClusterIP"` | |
-| serviceAccount.create | bool | `true` | |
-| serviceAccount.name | string | `nil` | |
-| tolerations | list | `[]` | |
-| volumePermissions.enabled | bool | `true` | |
-| volumePermissions.securityContext.runAsUser | int | `0` | |
-
-Specify each parameter using the `--set key=value[,key=value]` argument to `helm
-install`. For example,
-
-```console
-$ helm upgrade --install code-server \
- ci/helm-chart \
- --set persistence.enabled=false
-```
-
-The above command sets the the persistence storage to false.
-
-Alternatively, a YAML file that specifies the values for the above parameters
-can be provided while installing the chart. For example,
-
-```console
-$ helm upgrade --install code-server ci/helm-chart -f values.yaml
-```
-
-> **Tip**: You can use the default [values.yaml](values.yaml)
diff --git a/ci/helm-chart/templates/NOTES.txt b/ci/helm-chart/templates/NOTES.txt
index 17c25f646dc2..45c9aed3881d 100644
--- a/ci/helm-chart/templates/NOTES.txt
+++ b/ci/helm-chart/templates/NOTES.txt
@@ -15,9 +15,8 @@
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "code-server.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
- export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "code-server.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
- kubectl port-forward $POD_NAME 8080:80
+ kubectl port-forward --namespace {{ .Release.Namespace }} service/{{ include "code-server.fullname" . }} 8080:http
{{- end }}
Administrator credentials:
diff --git a/ci/helm-chart/templates/deployment.yaml b/ci/helm-chart/templates/deployment.yaml
index 9364a4706aa3..18bece028fc6 100644
--- a/ci/helm-chart/templates/deployment.yaml
+++ b/ci/helm-chart/templates/deployment.yaml
@@ -3,33 +3,41 @@ kind: Deployment
metadata:
name: {{ include "code-server.fullname" . }}
labels:
- app.kubernetes.io/name: {{ include "code-server.name" . }}
- helm.sh/chart: {{ include "code-server.chart" . }}
- app.kubernetes.io/instance: {{ .Release.Name }}
- app.kubernetes.io/managed-by: {{ .Release.Service }}
+ {{- include "code-server.labels" . | nindent 4 }}
+ {{- if .Values.annotations }}
+ annotations: {{- toYaml .Values.annotations | nindent 4 }}
+ {{- end }}
spec:
- replicas: 1
+ {{- if ne .Values.replicaCount nil }}
+ replicas: {{ .Values.replicaCount }}
+ {{- end }}
strategy:
type: Recreate
selector:
matchLabels:
- app.kubernetes.io/name: {{ include "code-server.name" . }}
- app.kubernetes.io/instance: {{ .Release.Name }}
+ {{- include "code-server.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
- app.kubernetes.io/name: {{ include "code-server.name" . }}
- app.kubernetes.io/instance: {{ .Release.Name }}
+ {{- include "code-server.selectorLabels" . | nindent 8 }}
+ {{- if .Values.podAnnotations }}
+ annotations: {{- toYaml .Values.podAnnotations | nindent 8 }}
+ {{- end }}
spec:
+ imagePullSecrets: {{- toYaml .Values.imagePullSecrets | nindent 8 }}
{{- if .Values.hostnameOverride }}
hostname: {{ .Values.hostnameOverride }}
{{- end }}
+ {{- if .Values.priorityClassName }}
+ priorityClassName: {{ .Values.priorityClassName }}
+ {{- end }}
{{- if .Values.securityContext.enabled }}
securityContext:
fsGroup: {{ .Values.securityContext.fsGroup }}
{{- end }}
- {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }}
+ {{- if or (and .Values.volumePermissions.enabled .Values.persistence.enabled) .Values.extraInitContainers }}
initContainers:
+ {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }}
- name: init-chmod-data
image: busybox:latest
imagePullPolicy: IfNotPresent
@@ -44,9 +52,13 @@ spec:
- name: data
mountPath: /home/coder
{{- end }}
+{{- if .Values.extraInitContainers }}
+{{ tpl .Values.extraInitContainers . | indent 6}}
+{{- end }}
+ {{- end }}
containers:
{{- if .Values.extraContainers }}
-{{ toYaml .Values.extraContainers | indent 8}}
+{{ tpl .Values.extraContainers . | indent 8}}
{{- end }}
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
@@ -55,6 +67,17 @@ spec:
securityContext:
runAsUser: {{ .Values.securityContext.runAsUser }}
{{- end }}
+ {{- if .Values.lifecycle.enabled }}
+ lifecycle:
+ {{- if .Values.lifecycle.postStart }}
+ postStart:
+ {{ toYaml .Values.lifecycle.postStart | nindent 14 }}
+ {{- end }}
+ {{- if .Values.lifecycle.preStop }}
+ preStop:
+ {{ toYaml .Values.lifecycle.preStop | nindent 14 }}
+ {{- end }}
+ {{- end }}
env:
{{- if .Values.extraVars }}
{{ toYaml .Values.extraVars | indent 10 }}
@@ -84,6 +107,7 @@ spec:
{{- range .Values.extraSecretMounts }}
- name: {{ .name }}
mountPath: {{ .mountPath }}
+ subPath: {{ .subPath | default "" }}
readOnly: {{ .readOnly }}
{{- end }}
{{- range .Values.extraVolumeMounts }}
@@ -96,14 +120,23 @@ spec:
- name: http
containerPort: 8080
protocol: TCP
+ {{- range .Values.extraPorts }}
+ - name: {{ .name }}
+ containerPort: {{ .port }}
+ protocol: {{ .protocol }}
+ {{- end }}
+ {{- if ne .Values.livenessProbe.enabled false }}
livenessProbe:
httpGet:
- path: /
+ path: /healthz
port: http
+ {{- end }}
+ {{- if ne .Values.readinessProbe.enabled false }}
readinessProbe:
httpGet:
- path: /
+ path: /healthz
port: http
+ {{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- with .Values.nodeSelector }}
@@ -112,7 +145,7 @@ spec:
{{- end }}
{{- with .Values.affinity }}
affinity:
- {{- toYaml . | nindent 8 }}
+ {{- tpl . $ | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
@@ -139,14 +172,23 @@ spec:
secretName: {{ .secretName }}
defaultMode: {{ .defaultMode }}
{{- end }}
+ {{- range .Values.extraConfigmapMounts }}
+ - name: {{ .name }}
+ configMap:
+ name: {{ .configMap }}
+ defaultMode: {{ .defaultMode }}
+ {{- end }}
{{- range .Values.extraVolumeMounts }}
- name: {{ .name }}
{{- if .existingClaim }}
persistentVolumeClaim:
claimName: {{ .existingClaim }}
- {{- else }}
+ {{- else if .hostPath }}
hostPath:
path: {{ .hostPath }}
type: Directory
+ {{- else }}
+ emptyDir:
+ {{- toYaml .emptyDir | nindent 10 }}
{{- end }}
{{- end }}
diff --git a/ci/helm-chart/templates/ingress.yaml b/ci/helm-chart/templates/ingress.yaml
index 07a3abd0b693..1da432074b29 100644
--- a/ci/helm-chart/templates/ingress.yaml
+++ b/ci/helm-chart/templates/ingress.yaml
@@ -1,7 +1,9 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "code-server.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
-{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
+{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1
+{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: extensions/v1beta1
@@ -16,6 +18,9 @@ metadata:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
+ {{- if .Values.ingress.ingressClassName }}
+ ingressClassName: {{ .Values.ingress.ingressClassName }}
+ {{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
@@ -27,6 +32,22 @@ spec:
{{- end }}
{{- end }}
rules:
+ {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion -}}
+ {{- range .Values.ingress.hosts }}
+ - host: {{ .host | quote }}
+ http:
+ paths:
+ {{- range .paths }}
+ - path: {{ . }}
+ pathType: Prefix
+ backend:
+ service:
+ name: {{ $fullName }}
+ port:
+ number: {{ $svcPort }}
+ {{- end }}
+ {{- end }}
+ {{- else -}}
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
@@ -39,3 +60,4 @@ spec:
{{- end }}
{{- end }}
{{- end }}
+{{- end }}
\ No newline at end of file
diff --git a/ci/helm-chart/templates/pvc.yaml b/ci/helm-chart/templates/pvc.yaml
index 2f1c87405886..206b834e930d 100644
--- a/ci/helm-chart/templates/pvc.yaml
+++ b/ci/helm-chart/templates/pvc.yaml
@@ -9,10 +9,7 @@ metadata:
{{ toYaml . | indent 4 }}
{{- end }}
labels:
- app.kubernetes.io/name: {{ include "code-server.name" . }}
- helm.sh/chart: {{ include "code-server.chart" . }}
- app.kubernetes.io/instance: {{ .Release.Name }}
- app.kubernetes.io/managed-by: {{ .Release.Service }}
+ {{- include "code-server.labels" . | nindent 4 }}
spec:
accessModes:
- {{ .Values.persistence.accessMode | quote }}
diff --git a/ci/helm-chart/templates/secrets.yaml b/ci/helm-chart/templates/secrets.yaml
index 6c600417a516..93e75800dffd 100644
--- a/ci/helm-chart/templates/secrets.yaml
+++ b/ci/helm-chart/templates/secrets.yaml
@@ -1,3 +1,4 @@
+{{- if not .Values.existingSecret }}
apiVersion: v1
kind: Secret
metadata:
@@ -5,14 +6,12 @@ metadata:
annotations:
"helm.sh/hook": "pre-install"
labels:
- app.kubernetes.io/name: {{ include "code-server.name" . }}
- helm.sh/chart: {{ include "code-server.chart" . }}
- app.kubernetes.io/instance: {{ .Release.Name }}
- app.kubernetes.io/managed-by: {{ .Release.Service }}
+ {{- include "code-server.labels" . | nindent 4 }}
type: Opaque
data:
- {{ if .Values.password }}
+ {{- if .Values.password }}
password: "{{ .Values.password | b64enc }}"
- {{ else }}
+ {{- else }}
password: "{{ randAlphaNum 24 | b64enc }}"
- {{ end }}
+ {{- end }}
+{{- end }}
diff --git a/ci/helm-chart/templates/service.yaml b/ci/helm-chart/templates/service.yaml
index 038b6cd0d23f..1b58af0b1acd 100644
--- a/ci/helm-chart/templates/service.yaml
+++ b/ci/helm-chart/templates/service.yaml
@@ -3,10 +3,7 @@ kind: Service
metadata:
name: {{ include "code-server.fullname" . }}
labels:
- app.kubernetes.io/name: {{ include "code-server.name" . }}
- helm.sh/chart: {{ include "code-server.chart" . }}
- app.kubernetes.io/instance: {{ .Release.Name }}
- app.kubernetes.io/managed-by: {{ .Release.Service }}
+ {{- include "code-server.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
@@ -14,6 +11,12 @@ spec:
targetPort: http
protocol: TCP
name: http
+ {{- range .Values.extraPorts }}
+ - port: {{ .port }}
+ targetPort: {{ .port }}
+ protocol: {{ .protocol }}
+ name: {{ .name }}
+ {{- end }}
selector:
app.kubernetes.io/name: {{ include "code-server.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
diff --git a/ci/helm-chart/templates/serviceaccount.yaml b/ci/helm-chart/templates/serviceaccount.yaml
index df9e1e37562b..2fa308fec172 100644
--- a/ci/helm-chart/templates/serviceaccount.yaml
+++ b/ci/helm-chart/templates/serviceaccount.yaml
@@ -3,9 +3,6 @@ apiVersion: v1
kind: ServiceAccount
metadata:
labels:
- app.kubernetes.io/name: {{ include "code-server.name" . }}
- helm.sh/chart: {{ include "code-server.chart" . }}
- app.kubernetes.io/instance: {{ .Release.Name }}
- app.kubernetes.io/managed-by: {{ .Release.Service }}
+ {{- include "code-server.labels" . | nindent 4 }}
name: {{ template "code-server.serviceAccountName" . }}
{{- end -}}
diff --git a/ci/helm-chart/templates/tests/test-connection.yaml b/ci/helm-chart/templates/tests/test-connection.yaml
index 2e67f56ec64c..dd81f8904e06 100644
--- a/ci/helm-chart/templates/tests/test-connection.yaml
+++ b/ci/helm-chart/templates/tests/test-connection.yaml
@@ -3,16 +3,13 @@ kind: Pod
metadata:
name: "{{ include "code-server.fullname" . }}-test-connection"
labels:
- app.kubernetes.io/name: {{ include "code-server.name" . }}
- helm.sh/chart: {{ include "code-server.chart" . }}
- app.kubernetes.io/instance: {{ .Release.Name }}
- app.kubernetes.io/managed-by: {{ .Release.Service }}
+ {{- include "code-server.labels" . | nindent 4 }}
annotations:
- "helm.sh/hook": test-success
+ "helm.sh/hook": test
spec:
containers:
- name: wget
image: busybox
command: ['wget']
- args: ['{{ include "code-server.fullname" . }}:{{ .Values.service.port }}']
+ args: ['{{ include "code-server.fullname" . }}:{{ .Values.service.port }}/healthz']
restartPolicy: Never
diff --git a/ci/helm-chart/values.yaml b/ci/helm-chart/values.yaml
index 7978c52c9764..9d07b928e53b 100644
--- a/ci/helm-chart/values.yaml
+++ b/ci/helm-chart/values.yaml
@@ -6,14 +6,22 @@ replicaCount: 1
image:
repository: codercom/code-server
- tag: '3.7.4'
+ tag: '4.133.0'
pullPolicy: Always
+# Specifies one or more secrets to be used when pulling images from a
+# private container repository
+# https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry
imagePullSecrets: []
+# - name: registry-creds
+
nameOverride: ""
fullnameOverride: ""
hostnameOverride: ""
+# The existing secret to use for code-server authentication in the frontend. the password is stored in the secret under the key `password`
+# existingSecret: ""
+
serviceAccount:
# Specifies whether a service account should be created
create: true
@@ -23,18 +31,19 @@ serviceAccount:
# If not set and create is true, a name is generated using the fullname template
name: ""
+# Specifies annotations for deployment
+annotations: {}
+
+# code-server.labels -- The Deployment labels. See:
+# https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
+labels: {}
+
podAnnotations: {}
podSecurityContext: {}
# fsGroup: 2000
-securityContext: {}
- # capabilities:
- # drop:
- # - ALL
- # readOnlyRootFilesystem: true
- # runAsNonRoot: true
- # runAsUser: 1000
+priorityClassName: ""
service:
type: ClusterIP
@@ -43,13 +52,12 @@ service:
ingress:
enabled: false
#annotations:
- # kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
#hosts:
# - host: code-server.example.loc
# paths:
# - /
-
+ ingressClassName: ""
#tls:
# - secretName: code-server
# hosts:
@@ -57,13 +65,26 @@ ingress:
# Optional additional arguments
extraArgs: []
-# - --allow-http
-# - --no-auth
+ # These are the arguments normally passed to code-server; run
+ # code-server --help for a list of available options.
+ #
+ # Each argument and parameter must have its own entry; if you use
+ # --param value on the command line, then enter it here as:
+ #
+ # - --param
+ # - value
+ #
+ # If you receive an error like "Unknown option --param value", it may be
+ # because both the parameter and value are specified as a single argument,
+ # rather than two separate arguments (e.g. "- --param value" on a line).
# Optional additional environment variables
extraVars: []
# - name: DISABLE_TELEMETRY
-# value: true
+# value: "true"
+# if dind is desired:
+# - name: DOCKER_HOST
+# value: "tcp://localhost:2376"
##
## Init containers parameters:
@@ -94,6 +115,12 @@ resources: {}
# cpu: 100m
# memory: 1000Mi
+livenessProbe:
+ enabled: true
+
+readinessProbe:
+ enabled: true
+
nodeSelector: {}
tolerations: []
@@ -117,33 +144,73 @@ persistence:
# existingClaim: ""
# hostPath: /data
-serviceAccount:
- create: true
- name:
+lifecycle:
+ enabled: false
+ # postStart:
+ # exec:
+ # command:
+ # - /bin/bash
+ # - -c
+ # - curl -s -L SOME_SCRIPT | bash
+
+ # for dind, the following may be helpful
+ # postStart:
+ # exec:
+ # command:
+ # - /bin/sh
+ # - -c
+ # - |
+ # sudo apt-get update \
+ # && sudo apt-get install -y docker.io
## Enable an Specify container in extraContainers.
## This is meant to allow adding code-server dependencies, like docker-dind.
extraContainers: |
-#- name: docker-dind
-# image: docker:19.03-dind
-# imagePullPolicy: IfNotPresent
-# resources:
-# requests:
-# cpu: 250m
-# memory: 256M
-# securityContext:
-# privileged: true
-# procMount: Default
-# env:
-# - name: DOCKER_TLS_CERTDIR
-# value: ""
-# - name: DOCKER_DRIVER
-# value: "overlay2"
+# If docker-dind is used, DOCKER_HOST env is mandatory to set in "extraVars"
+# - name: docker-dind
+# image: docker:28.3.2-dind
+# imagePullPolicy: IfNotPresent
+# resources:
+# requests:
+# cpu: 1
+# ephemeral-storage: "50Gi"
+# memory: 10Gi
+# securityContext:
+# privileged: true
+# procMount: Default
+# env:
+# - name: DOCKER_TLS_CERTDIR
+# value: "" # disable TLS setup
+# command:
+# - dockerd
+# - --host=unix:///var/run/docker.sock
+# - --host=tcp://0.0.0.0:2376
+
+
+extraInitContainers: |
+# - name: customization
+# image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
+# imagePullPolicy: IfNotPresent
+# env:
+# - name: SERVICE_URL
+# value: https://open-vsx.org/vscode/gallery
+# - name: ITEM_URL
+# value: https://open-vsx.org/vscode/item
+# command:
+# - sh
+# - -c
+# - |
+# code-server --install-extension ms-python.python
+# code-server --install-extension golang.Go
+# volumeMounts:
+# - name: data
+# mountPath: /home/coder
## Additional code-server secret mounts
extraSecretMounts: []
# - name: secret-files
# mountPath: /etc/secrets
+ # subPath: private.key # (optional)
# secretName: code-server-secret-files
# readOnly: true
@@ -154,6 +221,7 @@ extraVolumeMounts: []
# readOnly: true
# existingClaim: volume-claim
# hostPath: ""
+ # emptyDir: {}
extraConfigmapMounts: []
# - name: certs-configmap
@@ -161,3 +229,8 @@ extraConfigmapMounts: []
# subPath: certificates.crt # (optional)
# configMap: certs-configmap
# readOnly: true
+
+extraPorts: []
+ # - name: minecraft
+ # port: 25565
+ # protocol: tcp
diff --git a/ci/images/centos7/Dockerfile b/ci/images/centos7/Dockerfile
deleted file mode 100644
index a37e590bb216..000000000000
--- a/ci/images/centos7/Dockerfile
+++ /dev/null
@@ -1,32 +0,0 @@
-FROM centos:7
-
-ARG NODE_VERSION=v12.18.4
-RUN ARCH="$(uname -m | sed 's/86_64/64/; s/aarch64/arm64/')" && \
- curl -fsSL "https://nodejs.org/dist/$NODE_VERSION/node-$NODE_VERSION-linux-$ARCH.tar.xz" | tar -C /usr/local -xJ && \
- mv "/usr/local/node-$NODE_VERSION-linux-$ARCH" "/usr/local/node-$NODE_VERSION"
-ENV PATH=/usr/local/node-$NODE_VERSION/bin:$PATH
-RUN npm install -g yarn
-
-RUN yum groupinstall -y 'Development Tools'
-RUN yum install -y python2 libsecret-devel libX11-devel libxkbfile-devel
-
-RUN npm config set python python2
-
-RUN yum install -y epel-release && yum install -y jq
-RUN yum install -y rsync
-
-# Copied from ../debian10/Dockerfile
-# Install Go.
-RUN ARCH="$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/')" && \
- curl -fsSL "https://dl.google.com/go/go1.14.3.linux-$ARCH.tar.gz" | tar -C /usr/local -xz
-ENV GOPATH=/gopath
-# Ensures running this image as another user works.
-RUN mkdir -p $GOPATH && chmod -R 777 $GOPATH
-ENV PATH=/usr/local/go/bin:$GOPATH/bin:$PATH
-
-# Install Go dependencies
-ENV GO111MODULE=on
-RUN go get mvdan.cc/sh/v3/cmd/shfmt
-RUN go get github.com/goreleaser/nfpm/cmd/nfpm@v1.9.0
-
-RUN curl -fsSL https://get.docker.com | sh
diff --git a/ci/images/debian10/Dockerfile b/ci/images/debian10/Dockerfile
deleted file mode 100644
index 5e4a5f85927b..000000000000
--- a/ci/images/debian10/Dockerfile
+++ /dev/null
@@ -1,54 +0,0 @@
-FROM debian:10
-
-RUN apt-get update
-
-# Needed for debian repositories added below.
-RUN apt-get install -y curl gnupg
-
-# Installs node.
-RUN curl -fsSL https://deb.nodesource.com/setup_12.x | bash - && \
- apt-get install -y nodejs
-
-# Installs yarn.
-RUN curl -fsSL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
- echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
- apt-get update && apt-get install -y yarn
-
-# Installs VS Code build deps.
-RUN apt-get install -y build-essential \
- libsecret-1-dev \
- libx11-dev \
- libxkbfile-dev
-
-# Installs envsubst.
-RUN apt-get install -y gettext-base
-
-# Misc build dependencies.
-RUN apt-get install -y git rsync unzip jq
-
-# Installs shellcheck.
-RUN curl -fsSL https://github.com/koalaman/shellcheck/releases/download/v0.7.1/shellcheck-v0.7.1.linux.$(uname -m).tar.xz | \
- tar -xJ && \
- mv shellcheck*/shellcheck /usr/local/bin && \
- rm -R shellcheck*
-
-# Install Go.
-RUN ARCH="$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/')" && \
- curl -fsSL "https://dl.google.com/go/go1.14.3.linux-$ARCH.tar.gz" | tar -C /usr/local -xz
-ENV GOPATH=/gopath
-# Ensures running this image as another user works.
-RUN mkdir -p $GOPATH && chmod -R 777 $GOPATH
-ENV PATH=/usr/local/go/bin:$GOPATH/bin:$PATH
-
-# Install Go dependencies
-ENV GO111MODULE=on
-RUN go get mvdan.cc/sh/v3/cmd/shfmt
-RUN go get github.com/goreleaser/nfpm/cmd/nfpm@v1.9.0
-
-RUN VERSION="$(curl -fsSL https://storage.googleapis.com/kubernetes-release/release/stable.txt)" && \
- curl -fsSL "https://storage.googleapis.com/kubernetes-release/release/$VERSION/bin/linux/amd64/kubectl" > /usr/local/bin/kubectl \
- && chmod +x /usr/local/bin/kubectl
-RUN curl -fsSL https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
-RUN helm plugin install https://github.com/instrumenta/helm-kubeval
-
-RUN curl -fsSL https://get.docker.com | sh
diff --git a/ci/lib.sh b/ci/lib.sh
index d58c29cb1713..7c1f0d9e5914 100755
--- a/ci/lib.sh
+++ b/ci/lib.sh
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
+set -euo pipefail
pushd() {
builtin pushd "$@" > /dev/null
@@ -8,88 +9,116 @@ popd() {
builtin popd > /dev/null
}
-pkg_json_version() {
- jq -r .version package.json
-}
-
vscode_version() {
jq -r .version lib/vscode/package.json
}
os() {
- local os
- os=$(uname | tr '[:upper:]' '[:lower:]')
- if [[ $os == "linux" ]]; then
- # Alpine's ldd doesn't have a version flag but if you use an invalid flag
- # (like --version) it outputs the version to stderr and exits with 1.
- local ldd_output
- ldd_output=$(ldd --version 2>&1 || true)
- if echo "$ldd_output" | grep -iq musl; then
- os="alpine"
- fi
- elif [[ $os == "darwin" ]]; then
- os="macos"
- fi
- echo "$os"
+ osname=$(uname | tr '[:upper:]' '[:lower:]')
+ case $osname in
+ linux)
+ # Alpine's ldd doesn't have a version flag but if you use an invalid flag
+ # (like --version) it outputs the version to stderr and exits with 1.
+ # TODO: Better to check /etc/os-release; see ../install.sh.
+ ldd_output=$(ldd --version 2>&1 || true)
+ if echo "$ldd_output" | grep -iq musl; then
+ osname="alpine"
+ fi
+ ;;
+ darwin) osname="macos" ;;
+ cygwin* | mingw*) osname="windows" ;;
+ esac
+ echo "$osname"
}
arch() {
- case "$(uname -m)" in
- aarch64)
- echo arm64
- ;;
- x86_64)
- echo amd64
- ;;
- *)
- echo "unknown architecture $(uname -a)"
- exit 1
- ;;
+ cpu="$(uname -m)"
+ case "$cpu" in
+ aarch64) cpu=arm64 ;;
+ x86_64) cpu=amd64 ;;
esac
+ echo "$cpu"
}
-curl() {
- command curl -H "Authorization: token $GITHUB_TOKEN" "$@"
+rsync() {
+ command rsync -a --del "$@"
}
-# Grabs the most recent ci.yaml github workflow run that was successful and triggered from the same commit being pushd.
-# This will contain the artifacts we want.
-# https://developer.github.com/v3/actions/workflow-runs/#list-workflow-runs
-get_artifacts_url() {
- curl -fsSL 'https://api.github.com/repos/cdr/code-server/actions/workflows/ci.yaml/runs?status=success&event=push' | jq -r ".workflow_runs[] | select(.head_sha == \"$(git rev-parse HEAD)\") | .artifacts_url" | head -n 1
-}
+if [[ ! ${ARCH-} ]]; then
+ ARCH=$(arch)
+ export ARCH
+fi
-# Grabs the artifact's download url.
-# https://developer.github.com/v3/actions/artifacts/#list-workflow-run-artifacts
-get_artifact_url() {
- local artifact_name="$1"
- curl -fsSL "$(get_artifacts_url)" | jq -r ".artifacts[] | select(.name == \"$artifact_name\") | .archive_download_url" | head -n 1
-}
+if [[ ! ${OS-} ]]; then
+ OS=$(os)
+ export OS
+fi
-# Uses the above two functions to download a artifact into a directory.
-download_artifact() {
- local artifact_name="$1"
- local dst="$2"
+# RELEASE_PATH is the destination directory for the release from the root.
+# Defaults to release
+if [[ ! ${RELEASE_PATH-} ]]; then
+ RELEASE_PATH="release"
+ export RELEASE_PATH
+fi
- local tmp_file
- tmp_file="$(mktemp)"
+nodeOS() {
+ osname=$OS
+ case $osname in
+ macos) osname=darwin ;;
+ windows) osname=win32 ;;
+ esac
+ echo "$osname"
+}
- curl -fsSL "$(get_artifact_url "$artifact_name")" > "$tmp_file"
- unzip -q -o "$tmp_file" -d "$dst"
- rm "$tmp_file"
+nodeArch() {
+ cpu=$ARCH
+ case $cpu in
+ amd64) cpu=x64 ;;
+ esac
+ echo "$cpu"
}
-rsync() {
- command rsync -a --del "$@"
+run-steps() {
+ local -i failed=0
+ mkdir -p .cache
+ rm -f .cache/checklist
+ while (( $# )) ; do
+ local name=$1 ; shift
+ local fn=$1 ; shift
+ echo "$name..."
+ # Only run if an earlier step has not failed.
+ # For all failed steps, write out an empty checkbox.
+ if [[ $failed == 0 ]] ; then
+ if $fn | indent ; then
+ echo "- [X] $name" >> .cache/checklist
+ else
+ ((failed++))
+ echo "- [ ] $name" >> .cache/checklist
+ echo "Failed" | indent
+ fi
+ else
+ echo "- [ ] $name" >> .cache/checklist
+ echo "Skipped" | indent
+ fi
+ done
+ if [[ $failed != 0 ]] ; then
+ return 1
+ fi
}
-VERSION="$(pkg_json_version)"
-export VERSION
-ARCH="$(arch)"
-export ARCH
-OS=$(os)
-export OS
+quiet() {
+ "$@" >/dev/null
+}
-# RELEASE_PATH is the destination directory for the release from the root.
-# Defaults to release
-RELEASE_PATH="${RELEASE_PATH-release}"
+indent() {
+ local count=2
+ local space
+ space=$(printf "%${count}s")
+ sed "s/^/$space| /g"
+}
+
+# See gulpfile.reh.ts for available targets.
+if [[ ! ${VSCODE_TARGET-} ]]; then
+ VSCODE_TARGET="$(nodeOS)-$(nodeArch)"
+ export VSCODE_TARGET
+fi
diff --git a/ci/release-image/Dockerfile b/ci/release-image/Dockerfile
index a0b6aed7167b..4c91e291e0e8 100644
--- a/ci/release-image/Dockerfile
+++ b/ci/release-image/Dockerfile
@@ -1,19 +1,29 @@
-FROM debian:10
+# syntax=docker/dockerfile:experimental
+
+ARG BASE=debian:13
+FROM scratch AS packages
+COPY release-packages/code-server*.deb /tmp/
+
+FROM $BASE
RUN apt-get update \
- && apt-get install -y \
+ && apt-get install -y \
curl \
dumb-init \
+ git \
+ git-lfs \
htop \
locales \
- man \
+ lsb-release \
+ man-db \
nano \
- git \
+ openssh-client \
procps \
- ssh \
sudo \
- vim \
- lsb-release \
+ vim-tiny \
+ wget \
+ zsh \
+ && git lfs install \
&& rm -rf /var/lib/apt/lists/*
# https://wiki.debian.org/Locale#Manually
@@ -21,22 +31,25 @@ RUN sed -i "s/# en_US.UTF-8/en_US.UTF-8/" /etc/locale.gen \
&& locale-gen
ENV LANG=en_US.UTF-8
-RUN chsh -s /bin/bash
-ENV SHELL=/bin/bash
-
-RUN adduser --gecos '' --disabled-password coder && \
- echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd
+RUN if grep -q 1000 /etc/passwd; then \
+ userdel -r "$(id -un 1000)"; \
+ fi \
+ && adduser --gecos '' --disabled-password coder \
+ && echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd
-RUN ARCH="$(dpkg --print-architecture)" && \
- curl -fsSL "https://github.com/boxboat/fixuid/releases/download/v0.4.1/fixuid-0.4.1-linux-$ARCH.tar.gz" | tar -C /usr/local/bin -xzf - && \
- chown root:root /usr/local/bin/fixuid && \
- chmod 4755 /usr/local/bin/fixuid && \
- mkdir -p /etc/fixuid && \
- printf "user: coder\ngroup: coder\n" > /etc/fixuid/config.yml
+RUN ARCH="$(dpkg --print-architecture)" \
+ && curl -fsSL "https://github.com/boxboat/fixuid/releases/download/v0.6.0/fixuid-0.6.0-linux-$ARCH.tar.gz" | tar -C /usr/local/bin -xzf - \
+ && chown root:root /usr/local/bin/fixuid \
+ && chmod 4755 /usr/local/bin/fixuid \
+ && mkdir -p /etc/fixuid \
+ && printf "user: coder\ngroup: coder\n" > /etc/fixuid/config.yml
-COPY release-packages/code-server*.deb /tmp/
COPY ci/release-image/entrypoint.sh /usr/bin/entrypoint.sh
-RUN dpkg -i /tmp/code-server*$(dpkg --print-architecture).deb && rm /tmp/code-server*.deb
+RUN --mount=from=packages,src=/tmp,dst=/tmp/packages dpkg -i /tmp/packages/code-server*$(dpkg --print-architecture).deb
+
+# Allow users to have scripts run on container startup to prepare workspace.
+# https://github.com/coder/code-server/issues/5177
+ENV ENTRYPOINTD=${HOME}/entrypoint.d
EXPOSE 8080
# This way, if someone sets $DOCKER_USER, docker-exec will still work as
diff --git a/ci/release-image/Dockerfile.fedora b/ci/release-image/Dockerfile.fedora
new file mode 100644
index 000000000000..ec618530cb78
--- /dev/null
+++ b/ci/release-image/Dockerfile.fedora
@@ -0,0 +1,51 @@
+# syntax=docker/dockerfile:experimental
+
+ARG BASE=fedora:39
+FROM scratch AS packages
+COPY release-packages/code-server*.rpm /tmp/
+
+FROM $BASE
+
+RUN dnf update -y \
+ && dnf install -y \
+ curl \
+ git \
+ git-lfs \
+ htop \
+ nano \
+ openssh-clients \
+ procps \
+ wget \
+ zsh \
+ dumb-init \
+ glibc-langpack-en \
+ && rm -rf /var/cache/dnf
+RUN git lfs install
+
+ENV LANG=en_US.UTF-8
+RUN echo 'LANG="en_US.UTF-8"' > /etc/locale.conf
+
+RUN useradd -u 1000 coder && echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd
+
+RUN ARCH="$(uname -m | sed 's/x86_64/amd64/g' | sed 's/aarch64/arm64/g')" \
+ && curl -fsSL "https://github.com/boxboat/fixuid/releases/download/v0.6.0/fixuid-0.6.0-linux-$ARCH.tar.gz" | tar -C /usr/local/bin -xzf - \
+ && chown root:root /usr/local/bin/fixuid \
+ && chmod 4755 /usr/local/bin/fixuid \
+ && mkdir -p /etc/fixuid \
+ && printf "user: coder\ngroup: coder\n" > /etc/fixuid/config.yml
+
+COPY ci/release-image/entrypoint.sh /usr/bin/entrypoint.sh
+RUN --mount=from=packages,src=/tmp,dst=/tmp/packages rpm -i /tmp/packages/code-server*$(uname -m | sed 's/x86_64/amd64/g' | sed 's/aarch64/arm64/g').rpm
+
+# Allow users to have scripts run on container startup to prepare workspace.
+# https://github.com/coder/code-server/issues/5177
+ENV ENTRYPOINTD=${HOME}/entrypoint.d
+
+EXPOSE 8080
+# This way, if someone sets $DOCKER_USER, docker-exec will still work as
+# the uid will remain the same. note: only relevant if -u isn't passed to
+# docker-run.
+USER 1000
+ENV USER=coder
+WORKDIR /home/coder
+ENTRYPOINT ["/usr/bin/entrypoint.sh", "--bind-addr", "0.0.0.0:8080", "."]
diff --git a/ci/release-image/Dockerfile.opensuse b/ci/release-image/Dockerfile.opensuse
new file mode 100644
index 000000000000..f445d45c27b1
--- /dev/null
+++ b/ci/release-image/Dockerfile.opensuse
@@ -0,0 +1,51 @@
+# syntax=docker/dockerfile:experimental
+
+ARG BASE=opensuse/tumbleweed
+FROM scratch AS packages
+COPY release-packages/code-server*.rpm /tmp/
+
+FROM $BASE
+
+RUN zypper dup -y \
+ && zypper in -y \
+ curl \
+ git \
+ git-lfs \
+ htop \
+ nano \
+ openssh-clients \
+ procps \
+ wget \
+ zsh \
+ sudo \
+ catatonit \
+ && rm -rf /var/cache/zypp /var/cache/zypper
+RUN git lfs install
+
+ENV LANG=en_US.UTF-8
+RUN echo 'LANG="en_US.UTF-8"' > /etc/locale.conf
+
+RUN useradd -u 1000 coder && echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd
+
+RUN ARCH="$(uname -m | sed 's/x86_64/amd64/g' | sed 's/aarch64/arm64/g')" \
+ && curl -fsSL "https://github.com/boxboat/fixuid/releases/download/v0.6.0/fixuid-0.6.0-linux-$ARCH.tar.gz" | tar -C /usr/local/bin -xzf - \
+ && chown root:root /usr/local/bin/fixuid \
+ && chmod 4755 /usr/local/bin/fixuid \
+ && mkdir -p /etc/fixuid \
+ && printf "user: coder\ngroup: coder\n" > /etc/fixuid/config.yml
+
+COPY ci/release-image/entrypoint-catatonit.sh /usr/bin/entrypoint-catatonit.sh
+RUN --mount=from=packages,src=/tmp,dst=/tmp/packages rpm -i /tmp/packages/code-server*$(uname -m | sed 's/x86_64/amd64/g' | sed 's/aarch64/arm64/g').rpm
+
+# Allow users to have scripts run on container startup to prepare workspace.
+# https://github.com/coder/code-server/issues/5177
+ENV ENTRYPOINTD=${HOME}/entrypoint.d
+
+EXPOSE 8080
+# This way, if someone sets $DOCKER_USER, docker-exec will still work as
+# the uid will remain the same. note: only relevant if -u isn't passed to
+# docker-run.
+USER 1000
+ENV USER=coder
+WORKDIR /home/coder
+ENTRYPOINT ["/usr/bin/entrypoint-catatonit.sh", "--bind-addr", "0.0.0.0:8080", "."]
diff --git a/ci/release-image/build.sh b/ci/release-image/build.sh
deleted file mode 100755
index 5969e15ae9a6..000000000000
--- a/ci/release-image/build.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-main() {
- cd "$(dirname "$0")/../.."
- source ./ci/lib.sh
-
- docker build -t "codercom/code-server-$ARCH:$VERSION" -f ./ci/release-image/Dockerfile .
-}
-
-main "$@"
diff --git a/ci/release-image/docker-bake.hcl b/ci/release-image/docker-bake.hcl
new file mode 100644
index 000000000000..ecb0c313daed
--- /dev/null
+++ b/ci/release-image/docker-bake.hcl
@@ -0,0 +1,130 @@
+# Use this file from the top of the repo, with `-f ci/release-image/docker-bake.hcl`
+
+# Uses env var VERSION if set;
+# normally, this is set by ci/lib.sh
+variable "VERSION" {
+ default = "latest"
+}
+
+variable "DOCKER_REGISTRY" {
+ default = "docker.io/codercom/code-server"
+}
+
+variable "GITHUB_REGISTRY" {
+ default = "ghcr.io/coder/code-server"
+}
+
+group "default" {
+ targets = [
+ "code-server-debian-13",
+ "code-server-debian-12",
+ "code-server-ubuntu-focal",
+ "code-server-ubuntu-noble",
+ "code-server-ubuntu-resolute",
+ "code-server-fedora-39",
+ "code-server-opensuse-tumbleweed",
+ ]
+}
+
+function "prepend_hyphen_if_not_null" {
+ params = [tag]
+ result = notequal("","${tag}") ? "-${tag}" : "${tag}"
+}
+
+# use empty tag (tag="") to generate default tags
+function "gen_tags" {
+ params = [registry, tag]
+ result = notequal("","${registry}") ? [
+ notequal("", "${tag}") ? "${registry}:${tag}" : "${registry}:latest",
+ notequal("latest",VERSION) ? "${registry}:${VERSION}${prepend_hyphen_if_not_null(tag)}" : "",
+ ] : []
+}
+
+# helper function to generate tags for docker registry and github registry.
+# set (DOCKER|GITHUB)_REGISTRY="" to disable corresponding registry
+function "gen_tags_for_docker_and_ghcr" {
+ params = [tag]
+ result = concat(
+ gen_tags("${DOCKER_REGISTRY}", "${tag}"),
+ gen_tags("${GITHUB_REGISTRY}", "${tag}"),
+ )
+}
+
+target "code-server-debian-13" {
+ dockerfile = "ci/release-image/Dockerfile"
+ tags = concat(
+ gen_tags_for_docker_and_ghcr(""),
+ gen_tags_for_docker_and_ghcr("debian"),
+ gen_tags_for_docker_and_ghcr("trixie"),
+ )
+ platforms = ["linux/amd64", "linux/arm64"]
+}
+
+target "code-server-debian-12" {
+ dockerfile = "ci/release-image/Dockerfile"
+ tags = concat(
+ gen_tags_for_docker_and_ghcr("bookworm"),
+ )
+ args = {
+ BASE = "debian:12"
+ }
+ platforms = ["linux/amd64", "linux/arm64"]
+}
+
+target "code-server-ubuntu-focal" {
+ dockerfile = "ci/release-image/Dockerfile"
+ tags = concat(
+ gen_tags_for_docker_and_ghcr("focal"),
+ )
+ args = {
+ BASE = "ubuntu:focal"
+ }
+ platforms = ["linux/amd64", "linux/arm64"]
+}
+
+target "code-server-ubuntu-noble" {
+ dockerfile = "ci/release-image/Dockerfile"
+ tags = concat(
+ gen_tags_for_docker_and_ghcr("noble"),
+ gen_tags_for_docker_and_ghcr("ubuntu"),
+ )
+ args = {
+ BASE = "ubuntu:noble"
+ }
+ platforms = ["linux/amd64", "linux/arm64"]
+}
+
+target "code-server-ubuntu-resolute" {
+ dockerfile = "ci/release-image/Dockerfile"
+ tags = concat(
+ gen_tags_for_docker_and_ghcr("resolute"),
+ )
+ args = {
+ BASE = "ubuntu:resolute"
+ }
+ platforms = ["linux/amd64", "linux/arm64"]
+}
+
+target "code-server-fedora-39" {
+ dockerfile = "ci/release-image/Dockerfile.fedora"
+ tags = concat(
+ gen_tags_for_docker_and_ghcr("fedora"),
+ gen_tags_for_docker_and_ghcr("39"),
+ )
+ args = {
+ BASE = "fedora:39"
+ }
+ platforms = ["linux/amd64", "linux/arm64"]
+}
+
+target "code-server-opensuse-tumbleweed" {
+ dockerfile = "ci/release-image/Dockerfile.opensuse"
+ tags = concat(
+ gen_tags_for_docker_and_ghcr("opensuse"),
+ gen_tags_for_docker_and_ghcr("tumbleweed"),
+ )
+ args = {
+ BASE = "opensuse/tumbleweed"
+ }
+ platforms = ["linux/amd64", "linux/arm64"]
+}
diff --git a/ci/release-image/entrypoint-catatonit.sh b/ci/release-image/entrypoint-catatonit.sh
new file mode 100755
index 000000000000..d22acc6d237b
--- /dev/null
+++ b/ci/release-image/entrypoint-catatonit.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+set -eu
+
+# We do this first to ensure sudo works below when renaming the user.
+# Otherwise the current container UID may not exist in the passwd database.
+eval "$(fixuid -q)"
+
+if [ "${DOCKER_USER-}" ]; then
+ USER="$DOCKER_USER"
+ if [ "$DOCKER_USER" != "$(whoami)" ]; then
+ echo "$DOCKER_USER ALL=(ALL) NOPASSWD:ALL" | sudo tee -a /etc/sudoers.d/nopasswd > /dev/null
+ # Unfortunately we cannot change $HOME as we cannot move any bind mounts
+ # nor can we bind mount $HOME into a new home as that requires a privileged container.
+ sudo usermod --login "$DOCKER_USER" coder
+ sudo groupmod -n "$DOCKER_USER" coder
+
+ sudo sed -i "/coder/d" /etc/sudoers.d/nopasswd
+ fi
+fi
+
+# Allow users to have scripts run on container startup to prepare workspace.
+# https://github.com/coder/code-server/issues/5177
+if [ -d "${ENTRYPOINTD}" ]; then
+ find "${ENTRYPOINTD}" -type f -executable -print -exec {} \;
+fi
+
+exec catatonit -- /usr/bin/code-server "$@"
diff --git a/ci/release-image/entrypoint.sh b/ci/release-image/entrypoint.sh
index 4f2f7cfe2391..efe2f39d9bd9 100755
--- a/ci/release-image/entrypoint.sh
+++ b/ci/release-image/entrypoint.sh
@@ -6,15 +6,22 @@ set -eu
eval "$(fixuid -q)"
if [ "${DOCKER_USER-}" ]; then
- echo "$DOCKER_USER ALL=(ALL) NOPASSWD:ALL" | sudo tee -a /etc/sudoers.d/nopasswd > /dev/null
- # Unfortunately we cannot change $HOME as we cannot move any bind mounts
- # nor can we bind mount $HOME into a new home as that requires a privileged container.
- sudo usermod --login "$DOCKER_USER" coder
- sudo groupmod -n "$DOCKER_USER" coder
-
USER="$DOCKER_USER"
+ if [ -z "$(id -u "$DOCKER_USER" 2>/dev/null)" ]; then
+ echo "$DOCKER_USER ALL=(ALL) NOPASSWD:ALL" | sudo tee -a /etc/sudoers.d/nopasswd > /dev/null
+ # Unfortunately we cannot change $HOME as we cannot move any bind mounts
+ # nor can we bind mount $HOME into a new home as that requires a privileged container.
+ sudo usermod --login "$DOCKER_USER" coder
+ sudo groupmod -n "$DOCKER_USER" coder
+
+ sudo sed -i "/coder/d" /etc/sudoers.d/nopasswd
+ fi
+fi
- sudo sed -i "/coder/d" /etc/sudoers.d/nopasswd
+# Allow users to have scripts run on container startup to prepare workspace.
+# https://github.com/coder/code-server/issues/5177
+if [ -d "${ENTRYPOINTD}" ]; then
+ find "${ENTRYPOINTD}" -type f -executable -print -exec {} \;
fi
-dumb-init /usr/bin/code-server "$@"
+exec dumb-init /usr/bin/code-server "$@"
diff --git a/ci/steps/build-docker-image.sh b/ci/steps/build-docker-image.sh
deleted file mode 100755
index 16653a0e9ed2..000000000000
--- a/ci/steps/build-docker-image.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-main() {
- cd "$(dirname "$0")/../.."
- source ./ci/lib.sh
-
- ./ci/release-image/build.sh
-
- mkdir -p release-images
- docker save "codercom/code-server-$ARCH:$VERSION" > "release-images/code-server-$ARCH-$VERSION.tar"
-}
-
-main "$@"
diff --git a/ci/steps/docker-buildx-push.sh b/ci/steps/docker-buildx-push.sh
new file mode 100755
index 000000000000..6314063ffa54
--- /dev/null
+++ b/ci/steps/docker-buildx-push.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+main() {
+ cd "$(dirname "$0")/../.."
+ # NOTE@jsjoeio - this script assumes VERSION exists as an
+ # environment variable.
+
+ # NOTE@jsjoeio - this script assumes that you've downloaded
+ # the release-packages artifact to ./release-packages before
+ # running this docker buildx step
+ docker buildx bake -f ci/release-image/docker-bake.hcl --push
+}
+
+main "$@"
diff --git a/ci/steps/fmt.sh b/ci/steps/fmt.sh
deleted file mode 100755
index 7d6717f56e63..000000000000
--- a/ci/steps/fmt.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-main() {
- cd "$(dirname "$0")/../.."
-
- yarn --frozen-lockfile
-
- git submodule update --init
- # We do not `yarn vscode` to make fmt.sh faster.
- # If the patch fails to apply, then it's likely already applied
- yarn vscode:patch &> /dev/null || true
-
- yarn fmt
-}
-
-main "$@"
diff --git a/ci/steps/lint.sh b/ci/steps/lint.sh
deleted file mode 100755
index 671229f84caf..000000000000
--- a/ci/steps/lint.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-main() {
- cd "$(dirname "$0")/../.."
-
- yarn --frozen-lockfile
-
- git submodule update --init
- # We need to fetch VS Code's deps for lint dependencies.
- yarn vscode
-
- yarn lint
-}
-
-main "$@"
diff --git a/ci/steps/publish-npm.sh b/ci/steps/publish-npm.sh
deleted file mode 100755
index 7bd497d001cd..000000000000
--- a/ci/steps/publish-npm.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-main() {
- cd "$(dirname "$0")/../.."
- source ./ci/lib.sh
-
- if [[ ${CI-} ]]; then
- echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
- fi
-
- download_artifact npm-package ./release-npm-package
- # https://github.com/actions/upload-artifact/issues/38
- tar -xzf release-npm-package/package.tar.gz
- yarn publish --non-interactive release
-}
-
-main "$@"
diff --git a/ci/steps/push-docker-manifest.sh b/ci/steps/push-docker-manifest.sh
deleted file mode 100755
index 08d0fdacf2d1..000000000000
--- a/ci/steps/push-docker-manifest.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-main() {
- cd "$(dirname "$0")/../.."
- source ./ci/lib.sh
-
- download_artifact release-images ./release-images
- if [[ ${CI-} ]]; then
- echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
- fi
-
- for img in ./release-images/*; do
- docker load -i "$img"
- done
-
- # We have to ensure the amd64 and arm64 images exist on the remote registry
- # in order to build the manifest.
- # We don't put the arch in the tag to avoid polluting the main repository.
- # These other repositories are private so they don't pollute our organization namespace.
- docker push "codercom/code-server-amd64:$VERSION"
- docker push "codercom/code-server-arm64:$VERSION"
-
- export DOCKER_CLI_EXPERIMENTAL=enabled
-
- docker manifest create "codercom/code-server:$VERSION" \
- "codercom/code-server-amd64:$VERSION" \
- "codercom/code-server-arm64:$VERSION"
- docker manifest push --purge "codercom/code-server:$VERSION"
-
- docker manifest create "codercom/code-server:latest" \
- "codercom/code-server-amd64:$VERSION" \
- "codercom/code-server-arm64:$VERSION"
- docker manifest push --purge "codercom/code-server:latest"
-}
-
-main "$@"
diff --git a/ci/steps/release-packages.sh b/ci/steps/release-packages.sh
deleted file mode 100755
index ba8d61d5ce6f..000000000000
--- a/ci/steps/release-packages.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-main() {
- cd "$(dirname "$0")/../.."
-
- NODE_VERSION=v12.18.4
- NODE_OS="$(uname | tr '[:upper:]' '[:lower:]')"
- NODE_ARCH="$(uname -m | sed 's/86_64/64/; s/aarch64/arm64/')"
- curl -L "https://nodejs.org/dist/$NODE_VERSION/node-$NODE_VERSION-$NODE_OS-$NODE_ARCH.tar.gz" | tar -xz
- PATH="$PWD/node-$NODE_VERSION-$NODE_OS-$NODE_ARCH/bin:$PATH"
-
- # https://github.com/actions/upload-artifact/issues/38
- tar -xzf release-npm-package/package.tar.gz
-
- yarn release:standalone
- yarn test:standalone-release
- yarn package
-}
-
-main "$@"
diff --git a/ci/steps/release.sh b/ci/steps/release.sh
deleted file mode 100755
index 80083c67f37b..000000000000
--- a/ci/steps/release.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-main() {
- cd "$(dirname "$0")/../.."
-
- yarn --frozen-lockfile
- yarn vscode
- yarn build
- yarn build:vscode
- yarn release
-
- # https://github.com/actions/upload-artifact/issues/38
- mkdir -p release-npm-package
- tar -czf release-npm-package/package.tar.gz release
-}
-
-main "$@"
diff --git a/ci/steps/steps-lib.sh b/ci/steps/steps-lib.sh
new file mode 100755
index 000000000000..e71378e27f6c
--- /dev/null
+++ b/ci/steps/steps-lib.sh
@@ -0,0 +1,47 @@
+#!/usr/bin/env bash
+
+# This is a library which contains functions used inside ci/steps
+#
+# We separated it into it's own file so that we could easily unit test
+# these functions and helpers
+
+# Checks whether and environment variable is set.
+# Source: https://stackoverflow.com/a/62210688/3015595
+is_env_var_set() {
+ local name="${1:-}"
+ if test -n "${!name:-}"; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+# Checks whether a directory exists.
+directory_exists() {
+ local dir="${1:-}"
+ if [[ -d "${dir:-}" ]]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+# Checks whether a file exists.
+file_exists() {
+ local file="${1:-}"
+ if test -f "${file:-}"; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+# Checks whether a file is executable.
+is_executable() {
+ local file="${1:-}"
+ if [ -f "${file}" ] && [ -r "${file}" ] && [ -x "${file}" ]; then
+ return 0
+ else
+ return 1
+ fi
+}
diff --git a/ci/steps/test.sh b/ci/steps/test.sh
deleted file mode 100755
index 801b2adc83cd..000000000000
--- a/ci/steps/test.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-main() {
- cd "$(dirname "$0")/../.."
-
- yarn --frozen-lockfile
-
- git submodule update --init
- # We do not `yarn vscode` to make test.sh faster.
- # If the patch fails to apply, then it's likely already applied
- yarn vscode:patch &> /dev/null || true
-
- yarn test
-}
-
-main "$@"
diff --git a/doc/CONTRIBUTING.md b/doc/CONTRIBUTING.md
deleted file mode 100644
index 9425c90be317..000000000000
--- a/doc/CONTRIBUTING.md
+++ /dev/null
@@ -1,163 +0,0 @@
-
-
-# Contributing
-
-- [Pull Requests](#pull-requests)
-- [Requirements](#requirements)
-- [Development Workflow](#development-workflow)
-- [Build](#build)
-- [Structure](#structure)
- - [VS Code Patch](#vs-code-patch)
- - [Currently Known Issues](#currently-known-issues)
-
-
-
-- [Detailed CI and build process docs](../ci)
-
-## Pull Requests
-
-Please create a [GitHub Issue](https://github.com/cdr/code-server/issues) for each issue
-you'd like to address unless the proposed fix is minor.
-
-In your Pull Requests (PR), link to the issue that the PR solves.
-
-Please ensure that the base of your PR is the **master** branch. (Note: The default
-GitHub branch is the latest release branch, though you should point all of your changes to be merged into
-master).
-
-## Requirements
-
-The prerequisites for contributing to code-server are almost the same as those for
-[VS Code](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites).
-There are several differences, however. You must:
-
-- Use Node.js version 12.x (or greater)
-- Have [yarn](https://classic.yarnpkg.com/en/) installed (which is used to install JS packages and run development scripts)
-- Have [nfpm](https://github.com/goreleaser/nfpm) (which is used to build `.deb` and `.rpm` packages and [jq](https://stedolan.github.io/jq/) (used to build code-server releases) installed
-
-The [CI container](../ci/images/debian8/Dockerfile) is a useful reference for all
-of the dependencies code-server uses.
-
-## Development Workflow
-
-```shell
-yarn
-yarn vscode
-yarn watch
-# Visit http://localhost:8080 once the build is completed.
-```
-
-To develop inside an isolated Docker container:
-
-```shell
-./ci/dev/image/run.sh yarn
-./ci/dev/image/run.sh yarn vscode
-./ci/dev/image/run.sh yarn watch
-```
-
-`yarn watch` will live reload changes to the source.
-
-If you introduce changes to the patch and you've previously built, you
-must (1) manually reset VS Code and (2) run `yarn vscode:patch`.
-
-## Build
-
-You can build using:
-
-```shell
-./ci/dev/image/run.sh ./ci/steps/release.sh
-```
-
-Run your build with:
-
-```shell
-cd release
-yarn --production
-# Runs the built JavaScript with Node.
-node .
-```
-
-Build the release packages (make sure that you run `./ci/steps/release.sh` first):
-
-```shell
-IMAGE=centos7 ./ci/dev/image/run.sh ./ci/steps/release-packages.sh
-# The standalone release is in ./release-standalone
-# .deb, .rpm and the standalone archive are in ./release-packages
-```
-
-The `release.sh` script is equal to running:
-
-```shell
-yarn
-yarn vscode
-yarn build
-yarn build:vscode
-yarn release
-```
-
-And `release-packages.sh` is equal to:
-
-```shell
-yarn release:standalone
-yarn test:standalone-release
-yarn package
-```
-
-For a faster release build, you can run instead:
-
-```shell
-KEEP_MODULES=1 ./ci/steps/release.sh
-node ./release
-```
-
-## Structure
-
-The `code-server` script serves an HTTP API for login and starting a remote VS Code process.
-
-The CLI code is in [./src/node](./src/node) and the HTTP routes are implemented in
-[./src/node/app](./src/node/app).
-
-Most of the meaty parts are in the VS Code patch, which we described next.
-
-### VS Code Patch
-
-In v1 of code-server, we had a patch of VS Code that split the codebase into a front-end
-and a server. The front-end consisted of all UI code, while the server ran the extensions
-and exposed an API to the front-end for file access and all UI needs.
-
-Over time, Microsoft added support to VS Code to run it on the web. They have made
-the front-end open source, but not the server. As such, code-server v2 (and later) uses
-the VS Code front-end and implements the server. You can find this in
-[./ci/dev/vscode.patch](../ci/dev/vscode.patch) under the path `src/vs/server`.
-
-Other notable changes in our patch include:
-
-- Adding our build file, which includes our code and VS Code's web code
-- Allowing multiple extension directories (both user and built-in)
-- Modifying the loader, websocket, webview, service worker, and asset requests to
- use the URL of the page as a base (and TLS, if necessary for the websocket)
-- Sending client-side telemetry through the server
-- Allowing modification of the display language
-- Making it possible for us to load code on the client
-- Making extensions work in the browser
-- Making it possible to install extensions of any kind
-- Fixing issue with getting disconnected when your machine sleeps or hibernates
-- Adding connection type to web socket query parameters
-
-As the web portion of VS Code matures, we'll be able to shrink and possibly
-eliminate our patch. In the meantime, upgrading the VS Code version requires
-us to ensure that the patch is applied and works as intended. In the future,
-we'd like to run VS Code unit tests against our builds to ensure that features
-work as expected.
-
-To generate a new patch, run `yarn vscode:diff`
-
-**Note**: We have [extension docs](../ci/README.md) on the CI and build system.
-
-If the functionality you're working on does NOT depend on code from VS Code, please
-move it out and into code-server.
-
-### Currently Known Issues
-
-- Creating custom VS Code extensions and debugging them doesn't work
-- Extension profiling and tips are currently disabled
diff --git a/doc/FAQ.md b/doc/FAQ.md
deleted file mode 100644
index 5b334b606478..000000000000
--- a/doc/FAQ.md
+++ /dev/null
@@ -1,322 +0,0 @@
-
-
-# FAQ
-
-- [Questions?](#questions)
-- [iPad Status?](#ipad-status)
-- [How can I reuse my VS Code configuration?](#how-can-i-reuse-my-vs-code-configuration)
-- [Differences compared to VS Code?](#differences-compared-to-vs-code)
-- [How can I request a missing extension?](#how-can-i-request-a-missing-extension)
-- [How do I configure the marketplace URL?](#how-do-i-configure-the-marketplace-url)
-- [Where are extensions stored?](#where-are-extensions-stored)
-- [How is this different from VS Code Codespaces?](#how-is-this-different-from-vs-code-codespaces)
-- [How should I expose code-server to the internet?](#how-should-i-expose-code-server-to-the-internet)
-- [How do I securely access web services?](#how-do-i-securely-access-web-services)
- - [Sub-paths](#sub-paths)
- - [Sub-domains](#sub-domains)
-- [Multi-tenancy](#multi-tenancy)
-- [Docker in code-server container?](#docker-in-code-server-container)
-- [How can I disable telemetry?](#how-can-i-disable-telemetry)
-- [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 debug issues with code-server?](#how-do-i-debug-issues-with-code-server)
-- [Heartbeat File](#heartbeat-file)
-- [Healthz endpoint](#healthz-endpoint)
-- [How does the config file work?](#how-does-the-config-file-work)
-- [Isn't an install script piped into sh insecure?](#isnt-an-install-script-piped-into-sh-insecure)
-- [How do I make my keyboard shortcuts work?](#how-do-i-make-my-keyboard-shortcuts-work)
-- [Differences compared to Theia?](#differences-compared-to-theia)
-- [Enterprise](#enterprise)
-
-
-
-## Questions?
-
-Please file all questions and support requests at https://github.com/cdr/code-server/discussions.
-
-## iPad Status?
-
-Please see [./ipad.md](./ipad.md).
-
-## How can I reuse my VS Code configuration?
-
-The very popular [Settings Sync](https://marketplace.visualstudio.com/items?itemName=Shan.code-settings-sync) extension works.
-
-You can also pass `--user-data-dir ~/.vscode` to reuse your existing VS Code extensions and configuration.
-
-Or copy `~/.vscode` into `~/.local/share/code-server`.
-
-## Differences compared to VS Code?
-
-`code-server` takes the open source core of VS Code and allows you to run it in the browser.
-However, it is not entirely equivalent to Microsoft's VS Code.
-
-While the core of VS Code is open source, the marketplace and many published Microsoft extensions are not.
-
-Furthermore, Microsoft prohibits the use of any non-Microsoft VS Code from accessing their marketplace.
-
-See the [TOS](https://cdn.vsassets.io/v/M146_20190123.39/_content/Microsoft-Visual-Studio-Marketplace-Terms-of-Use.pdf).
-
-> Marketplace Offerings are intended for use only with Visual Studio Products and Services
-> and you may only install and use Marketplace Offerings with Visual Studio Products and Services.
-
-As a result, we cannot offer any extensions on the Microsoft marketplace. Instead,
-we have created our own marketplace for open source extensions.
-It works by scraping GitHub for VS Code extensions and building them. It's not perfect but getting
-better by the day with more and more extensions.
-
-These are the closed source extensions presently unavailable:
-
-1. [Live Share](https://visualstudio.microsoft.com/services/live-share)
- - We may implement something similar, see [#33](https://github.com/cdr/code-server/issues/33)
-1. [Remote Extensions (SSH, Containers, WSL)](https://github.com/microsoft/vscode-remote-release)
- - We may reimplement these at some point, see [#1315](https://github.com/cdr/code-server/issues/1315)
-
-For more about the closed source parts of VS Code, see [vscodium/vscodium](https://github.com/VSCodium/vscodium#why-does-this-exist).
-
-## How can I request a missing extension?
-
-Please open a new issue and select the `Extension request` template.
-
-If an extension is not available or does not work, you can grab its VSIX from its Github releases or
-build it yourself. Then run the `Extensions: Install from VSIX` command in the Command Palette and
-point to the .vsix file.
-
-See below for installing an extension from the cli.
-
-## How do I configure the marketplace URL?
-
-If you have your own marketplace that implements the VS Code Extension Gallery API, it is possible to
-point code-server to it by setting `$SERVICE_URL` and `$ITEM_URL`. These correspond directly
-to `serviceUrl` and `itemUrl` in VS Code's `product.json`.
-
-e.g. to use [open-vsx.org](https://open-vsx.org):
-
-```bash
-export SERVICE_URL=https://open-vsx.org/vscode/gallery
-export ITEM_URL=https://open-vsx.org/vscode/item
-```
-
-While you can technically use Microsoft's marketplace with these, please do not do so as it
-is against their terms of use. See [above](#differences-compared-to-vs-code) and this
-discussion regarding the use of the Microsoft URLs in forks:
-
-https://github.com/microsoft/vscode/issues/31168#issue-244533026
-
-These variables are most valuable to our enterprise customers for whom we have a self hosted marketplace product.
-
-## Where are extensions stored?
-
-Defaults to `~/.local/share/code-server/extensions`.
-
-If the `XDG_DATA_HOME` environment variable is set the data directory will be
-`$XDG_DATA_HOME/code-server/extensions`. In general we try to follow the XDG directory spec.
-
-You can install an extension on the CLI with:
-
-```bash
-# From the Coder extension marketplace
-code-server --install-extension ms-python.python
-
-# From a downloaded VSIX on the file system
-code-server --install-extension downloaded-ms-python.python.vsix
-```
-
-## How is this different from VS Code Codespaces?
-
-VS Code Codespaces is a closed source and paid service by Microsoft. It also allows you to access
-VS Code via the browser.
-
-However, code-server is free, open source and can be run on any machine without any limitations.
-
-While you can self host environments with VS Code Codespaces, you still need an Azure billing
-account and you have to access VS Code via the Codespaces web dashboard instead of directly
-connecting to your instance.
-
-## How should I expose code-server to the internet?
-
-Please follow [./guide.md](./guide.md) for our recommendations on setting up and using code-server.
-
-code-server only supports password authentication natively.
-
-**note**: code-server will rate limit password authentication attempts at 2 a minute and 12 an hour.
-
-If you want to use external authentication (i.e sign in with Google) you should handle this
-with a reverse proxy using something like [oauth2_proxy](https://github.com/pusher/oauth2_proxy)
-or [Cloudflare Access](https://teams.cloudflare.com/access).
-
-For HTTPS, you can use a self signed certificate by passing in just `--cert` or
-pass in an existing certificate by providing the path to `--cert` and the path to
-the key with `--cert-key`.
-
-The self signed certificate will be generated into
-`~/.local/share/code-server/self-signed.crt`.
-
-If `code-server` has been passed a certificate it will also respond to HTTPS
-requests and will redirect all HTTP requests to HTTPS.
-
-You can use [Let's Encrypt](https://letsencrypt.org/) to get a TLS certificate
-for free.
-
-Again, please follow [./guide.md](./guide.md) for our recommendations on setting up and using code-server.
-
-## How do I securely access web services?
-
-code-server is capable of proxying to any port using either a subdomain or a
-subpath which means you can securely access these services using code-server's
-built-in authentication.
-
-### Sub-paths
-
-Just browse to `/proxy//`.
-
-### Sub-domains
-
-You will need a DNS entry that points to your server for each port you want to
-access. You can either set up a wildcard DNS entry for `*.` if your domain
-name registrar supports it or you can create one for every port you want to
-access (`3000.`, `8080.`, etc).
-
-You should also set up TLS certificates for these subdomains, either using a
-wildcard certificate for `*.` or individual certificates for each port.
-
-Start code-server with the `--proxy-domain` flag set to your domain.
-
-```
-code-server --proxy-domain
-```
-
-Now you can browse to `.`. Note that this uses the host header so
-ensure your reverse proxy forwards that information if you are using one.
-
-## Multi-tenancy
-
-If you want to run multiple code-servers on shared infrastructure, we recommend using virtual
-machines with a VM per user. This will easily allow users to run a docker daemon. If you want
-to use kubernetes, you'll definitely want to use [kubevirt](https://kubevirt.io) to give each
-user a virtual machine instead of just a container.
-
-## Docker in code-server container?
-
-If you'd like to access docker inside of code-server, mount the docker socket in from `/var/run/docker.sock`.
-Install the docker CLI in the code-server container and you should be able to access the daemon!
-
-You can even make volume mounts work. Lets say you want to run a container and mount in
-`/home/coder/myproject` into it from inside the `code-server` container. You need to make sure
-the docker daemon's `/home/coder/myproject` is the same as the one mounted inside the `code-server`
-container and the mount will just work.
-
-## How can I disable telemetry?
-
-Use the `--disable-telemetry` flag to completely disable telemetry. We use the
-data collected only to improve code-server.
-
-## How does code-server decide what workspace or folder to open?
-
-code-server tries the following in order:
-
-1. The `workspace` query parameter.
-2. The `folder` query parameter.
-3. The workspace or directory passed on the command line.
-4. The last opened workspace or directory.
-
-## How do I debug issues with code-server?
-
-First run code-server with at least `debug` logging (or `trace` to be really
-thorough) by setting the `--log` flag or the `LOG_LEVEL` environment variable.
-`-vvv` and `--verbose` are aliases for `--log trace`.
-
-```
-code-server --log debug
-```
-
-Once this is done, replicate the issue you're having then collect logging
-information from the following places:
-
-1. The most recent files from `~/.local/share/code-server/coder-logs`.
-2. The most recently created directory in the `~/.local/share/code-server/logs` directory.
-3. The browser console and network tabs.
-
-Additionally, collecting core dumps (you may need to enable them first) if
-code-server crashes can be helpful.
-
-## Heartbeat File
-
-`code-server` touches `~/.local/share/code-server/heartbeat` once a minute as long
-as there is an active browser connection.
-
-If you want to shutdown `code-server` if there hasn't been an active connection in X minutes
-you can do so by continuously checking the last modified time on the heartbeat file and if it is
-older than X minutes, kill `code-server`.
-
-[#1636](https://github.com/cdr/code-server/issues/1636) will make the experience here better.
-
-## Healthz endpoint
-
-`code-server` exposes an endpoint at `/healthz` which can be used to check
-whether `code-server` is up without triggering a heartbeat. The response will
-include a status (`alive` or `expired`) and a timestamp for the last heartbeat
-(defaults to `0`). This endpoint does not require authentication.
-
-```json
-{
- "status": "alive",
- "lastHeartbeat": 1599166210566
-}
-```
-
-## How does the config file work?
-
-When `code-server` starts up, it creates a default config file in `~/.config/code-server/config.yaml` that looks
-like this:
-
-```yaml
-bind-addr: 127.0.0.1:8080
-auth: password
-password: mewkmdasosafuio3422 # This is randomly generated for each config.yaml
-cert: false
-```
-
-Each key in the file maps directly to a `code-server` flag. Run `code-server --help` to see
-a listing of all the flags.
-
-The default config here says to listen on the loopback IP port 8080, enable password authorization
-and no TLS. Any flags passed to `code-server` will take priority over the config file.
-
-The `--config` flag or `$CODE_SERVER_CONFIG` can be used to change the config file's location.
-
-The default location also respects `$XDG_CONFIG_HOME`.
-
-## Isn't an install script piped into sh insecure?
-
-Please give
-[this wonderful blogpost](https://sandstorm.io/news/2015-09-24-is-curl-bash-insecure-pgp-verified-install) by
-[sandstorm.io](https://sandstorm.io) a read.
-
-## How do I make my keyboard shortcuts work?
-
-Many shortcuts will not work by default as they'll be caught by the browser.
-
-If you use Chrome you can get around this by installing the PWA.
-
-Once you've entered the editor, click the "plus" icon present in the URL toolbar area.
-This will install a Chrome PWA and now all keybindings will work!
-
-For other browsers you'll have to remap keybindings unfortunately.
-
-## Differences compared to Theia?
-
-[Theia](https://github.com/eclipse-theia/theia) is a browser IDE loosely based on VS Code. It uses the same
-text editor library named [Monaco](https://github.com/Microsoft/monaco-editor) and the same
-extension API but everything else is very different. It also uses [open-vsx.org](https://open-vsx.org)
-for extensions which has an order of magnitude less extensions than our marketplace.
-See [#1473](https://github.com/cdr/code-server/issues/1473).
-
-You can't just use your VS Code config in Theia like you can with code-server.
-
-To summarize, code-server is a patched fork of VS Code to run in the browser whereas
-Theia takes some parts of VS Code but is an entirely different editor.
-
-## Enterprise
-
-Visit [our enterprise page](https://coder.com) for more information about our
-enterprise offerings.
diff --git a/doc/assets/screenshot.png b/doc/assets/screenshot.png
deleted file mode 100644
index 77ab4611e9ed..000000000000
Binary files a/doc/assets/screenshot.png and /dev/null differ
diff --git a/doc/guide.md b/doc/guide.md
deleted file mode 100644
index 46abd083598d..000000000000
--- a/doc/guide.md
+++ /dev/null
@@ -1,307 +0,0 @@
-
-
-# Setup Guide
-
-- [1. Acquire a remote machine](#1-acquire-a-remote-machine)
- - [Requirements](#requirements)
- - [Google Cloud](#google-cloud)
-- [2. Install code-server](#2-install-code-server)
-- [3. Expose code-server](#3-expose-code-server)
- - [SSH forwarding](#ssh-forwarding)
- - [Let's Encrypt](#lets-encrypt)
- - [NGINX](#nginx)
- - [Self Signed Certificate](#self-signed-certificate)
- - [Change the password?](#change-the-password)
- - [How do I securely access development web services?](#how-do-i-securely-access-development-web-services)
-
-
-
-This guide demonstrates how to setup and use `code-server`.
-To reiterate, `code-server` lets you run VS Code on a remote server and then access it via a browser.
-
-Further docs are at:
-
-- [README](../README.md) for a general overview
-- [INSTALL](../doc/install.md) for installation
-- [FAQ](./FAQ.md) for common questions.
-- [CONTRIBUTING](../doc/CONTRIBUTING.md) for development docs
-
-We highly recommend reading the [FAQ](./FAQ.md) on the [Differences compared to VS Code](./FAQ.md#differences-compared-to-vs-code) before beginning.
-
-We'll walk you through acquiring a remote machine to run `code-server` on
-and then exposing `code-server` so you can securely access it.
-
-## 1. Acquire a remote machine
-
-First, you need a machine to run `code-server` on. You can use a physical
-machine you have lying around or use a VM on GCP/AWS.
-
-### Requirements
-
-For a good experience, we recommend at least:
-
-- 1 GB of RAM
-- 2 cores
-
-You can use whatever linux distribution floats your boat but in this guide we assume Debian on Google Cloud.
-
-### Google Cloud
-
-For demonstration purposes, this guide assumes you're using a VM on GCP but you should be
-able to easily use any machine or VM provider.
-
-You can sign up at https://console.cloud.google.com/getting-started. You'll get a 12 month \$300
-free trial.
-
-Once you've signed up and created a GCP project, create a new Compute Engine VM Instance.
-
-1. Navigate to `Compute Engine -> VM Instances` on the sidebar.
-2. Now click `Create Instance` to create a new instance.
-3. Name it whatever you want.
-4. Choose the region closest to you based on [gcping.com](http://www.gcping.com).
-5. Any zone is fine.
-6. We'd recommend a `E2` series instance from the General-purpose family.
- - Change the type to custom and set at least 2 cores and 2 GB of ram.
- - Add more vCPUs and memory as you prefer, you can edit after creating the instance as well.
- - https://cloud.google.com/compute/docs/machine-types#general_purpose
-7. We highly recommend switching the persistent disk to an SSD of at least 32 GB.
- - Click `Change` under `Boot Disk` and change the type to `SSD Persistent Disk` and the size
- to `32`.
- - You can always grow your disk later.
-8. Navigate to `Networking -> Network interfaces` and edit the existing interface
- to use a static external IP.
- - Click done to save network interface changes.
-9. If you do not have a [project wide SSH key](https://cloud.google.com/compute/docs/instances/adding-removing-ssh-keys#project-wide), navigate to `Security -> SSH Keys` and add your public key there.
-10. Click create!
-
-Remember, you can shutdown your server when not in use to lower costs.
-
-We highly recommend learning to use the [`gcloud`](https://cloud.google.com/sdk/gcloud) cli
-to avoid the slow dashboard.
-
-## 2. Install code-server
-
-We have a [script](../install.sh) to install `code-server` for Linux, macOS and FreeBSD.
-
-It tries to use the system package manager if possible.
-
-First run to print out the install process:
-
-```bash
-curl -fsSL https://code-server.dev/install.sh | sh -s -- --dry-run
-```
-
-Now to actually install:
-
-```bash
-curl -fsSL https://code-server.dev/install.sh | sh
-```
-
-The install script will print out how to run and start using `code-server`.
-
-Docs on the install script, manual installation and docker image are at [./install.md](./install.md).
-
-## 3. Expose code-server
-
-**Never**, **ever** expose `code-server` directly to the internet without some form of authentication
-and encryption as someone can completely takeover your machine with the terminal.
-
-By default, `code-server` will enable password authentication which will require you to copy the
-password from the`code-server`config file to login. It will listen on`localhost` to avoid exposing
-itself to the world. This is fine for testing but will not work if you want to access `code-server`
-from a different machine.
-
-There are several approaches to securely operating and exposing `code-server`.
-
-**tip**: You can list the full set of `code-server` options with `code-server --help`
-
-### SSH forwarding
-
-We highly recommend this approach for not requiring any additional setup, you just need an
-SSH server on your remote machine. The downside is you won't be able to access `code-server`
-on any machine without an SSH client like on iPad. If that's important to you, skip to [Let's Encrypt](#lets-encrypt).
-
-First, ssh into your instance and edit your `code-server` config file to disable password authentication.
-
-```bash
-# Replaces "auth: password" with "auth: none" in the code-server config.
-sed -i.bak 's/auth: password/auth: none/' ~/.config/code-server/config.yaml
-```
-
-Restart `code-server` with (assuming you followed the guide):
-
-```bash
-sudo systemctl restart code-server@$USER
-```
-
-Now forward local port 8080 to `127.0.0.1:8080` on the remote instance by running the following command on your local machine.
-
-Recommended reading: https://help.ubuntu.com/community/SSH/OpenSSH/PortForwarding.
-
-```bash
-# -N disables executing a remote shell
-ssh -N -L 8080:127.0.0.1:8080 [user]@
-```
-
-Now if you access http://127.0.0.1:8080 locally, you should see `code-server`!
-
-If you want to make the SSH port forwarding persistent we recommend using
-[mutagen](https://mutagen.io/documentation/introduction/installation).
-
-```
-# Same as the above SSH command but runs in the background continuously.
-# Add `mutagen daemon start` to your ~/.bashrc to start the mutagen daemon when you open a shell.
-mutagen forward create --name=code-server tcp:127.0.0.1:8080 :tcp:127.0.0.1:8080
-```
-
-We also recommend adding the following lines to your `~/.ssh/config` to quickly detect bricked SSH connections:
-
-```bash
-Host *
-ServerAliveInterval 5
-ExitOnForwardFailure yes
-```
-
-You can also forward your SSH and GPG agent to the instance to securely access GitHub
-and sign commits without copying your keys.
-
-1. https://developer.github.com/v3/guides/using-ssh-agent-forwarding/
-2. https://wiki.gnupg.org/AgentForwarding
-
-### Let's Encrypt
-
-[Let's Encrypt](https://letsencrypt.org) is a great option if you want to access `code-server` on an iPad
-or do not want to use SSH forwarding. This does require that the remote machine be exposed to the internet.
-
-Assuming you have been following the guide, edit your instance and checkmark the allow HTTP/HTTPS traffic options.
-
-1. You'll need to buy a domain name. We recommend [Google Domains](https://domains.google.com).
-2. Add an A record to your domain with your instance's IP.
-3. Install caddy https://caddyserver.com/docs/download#debian-ubuntu-raspbian.
-
-```bash
-echo "deb [trusted=yes] https://apt.fury.io/caddy/ /" \
- | sudo tee -a /etc/apt/sources.list.d/caddy-fury.list
-sudo apt update
-sudo apt install caddy
-```
-
-4. Replace `/etc/caddy/Caddyfile` with sudo to look like this:
-
-```
-mydomain.com
-
-reverse_proxy 127.0.0.1:8080
-```
-
-Remember to replace `mydomain.com` with your domain name!
-
-5. Reload caddy with:
-
-```bash
-sudo systemctl reload caddy
-```
-
-Visit `https://` to access `code-server`. Congratulations!
-
-In a future release we plan to integrate Let's Encrypt directly with `code-server` to avoid
-the dependency on caddy.
-
-#### NGINX
-
-If you prefer to use NGINX instead of Caddy then please follow steps 1-2 above and then:
-
-3. Install `nginx`:
-
-```bash
-sudo apt update
-sudo apt install -y nginx certbot python-certbot-nginx
-```
-
-4. Put the following config into `/etc/nginx/sites-available/code-server` with sudo:
-
-```nginx
-server {
- listen 80;
- listen [::]:80;
- server_name mydomain.com;
-
- location / {
- proxy_pass http://localhost:8080/;
- proxy_set_header Host $host;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection upgrade;
- proxy_set_header Accept-Encoding gzip;
- }
-}
-```
-
-Remember to replace `mydomain.com` with your domain name!
-
-5. Enable the config:
-
-```bash
-sudo ln -s ../sites-available/code-server /etc/nginx/sites-enabled/code-server
-sudo certbot --non-interactive --redirect --agree-tos --nginx -d mydomain.com -m me@example.com
-```
-
-Make sure to substitute `me@example.com` with your actual email.
-
-Visit `https://` to access `code-server`. Congratulations!
-
-### Self Signed Certificate
-
-**note:** Self signed certificates do not work with iPad normally. See [./ipad.md](./ipad.md) for details.
-
-Recommended reading: https://security.stackexchange.com/a/8112.
-
-We recommend this as a last resort because self signed certificates do not work with iPads and can
-cause other bizarre issues. Not to mention all the warnings when you access `code-server`.
-Only use this if:
-
-1. You do not want to buy a domain or you cannot expose the remote machine to the internet.
-2. You do not want to use SSH forwarding.
-
-ssh into your instance and edit your code-server config file to use a randomly generated self signed certificate:
-
-```bash
-# Replaces "cert: false" with "cert: true" in the code-server config.
-sed -i.bak 's/cert: false/cert: true/' ~/.config/code-server/config.yaml
-# Replaces "bind-addr: 127.0.0.1:8080" with "bind-addr: 0.0.0.0:443" in the code-server config.
-sed -i.bak 's/bind-addr: 127.0.0.1:8080/bind-addr: 0.0.0.0:443/' ~/.config/code-server/config.yaml
-# Allows code-server to listen on port 443.
-sudo setcap cap_net_bind_service=+ep /usr/lib/code-server/lib/node
-```
-
-Assuming you have been following the guide, restart `code-server` with:
-
-```bash
-sudo systemctl restart code-server@$USER
-```
-
-Edit your instance and checkmark the allow HTTPS traffic option.
-
-Visit `https://` to access `code-server`.
-You'll get a warning when accessing but if you click through you should be good.
-
-To avoid the warnings, you can use [mkcert](https://mkcert.dev) to create a self signed certificate
-trusted by your OS and then pass it into `code-server` via the `cert` and `cert-key` config
-fields.
-
-### Change the password?
-
-Edit the `password` field in the `code-server` config file at `~/.config/code-server/config.yaml`
-and then restart `code-server` with:
-
-```bash
-sudo systemctl restart code-server@$USER
-```
-
-Alternatively, you can specify the SHA-256 of your password at the `hashedPassword` field in the config file.
-The `hashedPassword` field takes precedence over `password`.
-
-### How do I securely access development web services?
-
-If you're working on a web service and want to access it locally, `code-server` can proxy it for you.
-
-See the [FAQ](./FAQ.md#how-do-i-securely-access-web-services).
diff --git a/doc/install.md b/doc/install.md
deleted file mode 100644
index c813d537ee7e..000000000000
--- a/doc/install.md
+++ /dev/null
@@ -1,206 +0,0 @@
-
-
-# Install
-
-- [Upgrading](#upgrading)
-- [install.sh](#installsh)
- - [Flags](#flags)
- - [Detection Reference](#detection-reference)
-- [Debian, Ubuntu](#debian-ubuntu)
-- [Fedora, CentOS, RHEL, SUSE](#fedora-centos-rhel-suse)
-- [Arch Linux](#arch-linux)
-- [yarn, npm](#yarn-npm)
-- [macOS](#macos)
-- [Standalone Releases](#standalone-releases)
-- [Docker](#docker)
-- [helm](#helm)
-
-
-
-This document demonstrates how to install `code-server` on
-various distros and operating systems.
-
-## Upgrading
-
-When upgrading you can just install the new version over the old one. code-server
-maintains all user data in `~/.local/share/code-server` so that it is preserved in between
-installations.
-
-## install.sh
-
-We have a [script](../install.sh) to install code-server for Linux, macOS and FreeBSD.
-
-It tries to use the system package manager if possible.
-
-First run to print out the install process:
-
-```bash
-curl -fsSL https://code-server.dev/install.sh | sh -s -- --dry-run
-```
-
-Now to actually install:
-
-```bash
-curl -fsSL https://code-server.dev/install.sh | sh
-```
-
-The script will print out how to run and start using code-server.
-
-If you believe an install script used with `curl | sh` is insecure, please give
-[this wonderful blogpost](https://sandstorm.io/news/2015-09-24-is-curl-bash-insecure-pgp-verified-install) by
-[sandstorm.io](https://sandstorm.io) a read.
-
-If you'd still prefer manual installation despite the below [detection reference](#detection-reference) and `--dry-run`
-then continue on for docs on manual installation. The [`install.sh`](../install.sh) script runs the _exact_ same
-commands presented in the rest of this document.
-
-### Flags
-
-- `--dry-run` to echo the commands for the install process without running them.
-- `--method` to choose the installation method.
- - `--method=detect` to detect the package manager but fallback to `--method=standalone`.
- - `--method=standalone` to install a standalone release archive into `~/.local`.
-- `--prefix=/usr/local` to install a standalone release archive system wide.
-- `--version=X.X.X` to install version `X.X.X` instead of latest.
-- `--help` to see full usage docs.
-
-### Detection Reference
-
-- For Debian, Ubuntu and Raspbian it will install the latest deb package.
-- For Fedora, CentOS, RHEL and openSUSE it will install the latest rpm package.
-- For Arch Linux it will install the AUR package.
-- For any unrecognized Linux operating system it will install the latest standalone release into `~/.local`.
-
- - Add `~/.local/bin` to your `$PATH` to run code-server.
-
-- For macOS it will install the Homebrew package.
-
- - If Homebrew is not installed it will install the latest standalone release into `~/.local`.
- - Add `~/.local/bin` to your `$PATH` to run code-server.
-
-- For FreeBSD, it will install the [npm package](#yarn-npm) with `yarn` or `npm`.
-
-- If ran on an architecture with no releases, it will install the [npm package](#yarn-npm) with `yarn` or `npm`.
- - We only have releases for amd64 and arm64 presently.
- - The [npm package](#yarn-npm) builds the native modules on postinstall.
-
-## Debian, Ubuntu
-
-```bash
-curl -fOL https://github.com/cdr/code-server/releases/download/v3.7.4/code-server_3.7.4_amd64.deb
-sudo dpkg -i code-server_3.7.4_amd64.deb
-sudo systemctl enable --now code-server@$USER
-# Now visit http://127.0.0.1:8080. Your password is in ~/.config/code-server/config.yaml
-```
-
-## Fedora, CentOS, RHEL, SUSE
-
-```bash
-curl -fOL https://github.com/cdr/code-server/releases/download/v3.7.4/code-server-3.7.4-amd64.rpm
-sudo rpm -i code-server-3.7.4-amd64.rpm
-sudo systemctl enable --now code-server@$USER
-# Now visit http://127.0.0.1:8080. Your password is in ~/.config/code-server/config.yaml
-```
-
-## Arch Linux
-
-```bash
-# Installs code-server from the AUR using yay.
-yay -S code-server
-sudo systemctl enable --now code-server@$USER
-# Now visit http://127.0.0.1:8080. Your password is in ~/.config/code-server/config.yaml
-```
-
-```bash
-# Installs code-server from the AUR with plain makepkg.
-git clone https://aur.archlinux.org/code-server.git
-cd code-server
-makepkg -si
-sudo systemctl enable --now code-server@$USER
-# Now visit http://127.0.0.1:8080. Your password is in ~/.config/code-server/config.yaml
-```
-
-## yarn, npm
-
-We recommend installing with `yarn` or `npm` when:
-
-1. You aren't on `amd64` or `arm64`.
-2. If you're on Linux with glibc < v2.17 or glibcxx < v3.4.18
-
-**note:** Installing via `yarn` or `npm` builds native modules on install and so requires C dependencies.
-See [./npm.md](./npm.md) for installing these dependencies.
-
-You will need at least node v12 installed. See [#1633](https://github.com/cdr/code-server/issues/1633).
-
-```bash
-yarn global add code-server
-# Or: npm install -g code-server
-code-server
-# Now visit http://127.0.0.1:8080. Your password is in ~/.config/code-server/config.yaml
-```
-
-## macOS
-
-```bash
-brew install code-server
-brew services start code-server
-# Now visit http://127.0.0.1:8080. Your password is in ~/.config/code-server/config.yaml
-```
-
-## Standalone Releases
-
-We publish self contained `.tar.gz` archives for every release on [github](https://github.com/cdr/code-server/releases).
-They bundle the node binary and `node_modules`.
-
-These are created from the [npm package](#yarn-npm) and the rest of the releases are created from these.
-Only requirement is glibc >= 2.17 && glibcxx >= v3.4.18 on Linux and for macOS there is no minimum system requirement.
-
-1. Download the latest release archive for your system from [github](https://github.com/cdr/code-server/releases).
-2. Unpack the release.
-3. You can run code-server by executing `./bin/code-server`.
-
-You can add the code-server `bin` directory to your `$PATH` to easily execute `code-server`
-without the full path every time.
-
-Here is an example script for installing and using a standalone `code-server` release on Linux:
-
-```bash
-mkdir -p ~/.local/lib ~/.local/bin
-curl -fL https://github.com/cdr/code-server/releases/download/v3.7.4/code-server-3.7.4-linux-amd64.tar.gz \
- | tar -C ~/.local/lib -xz
-mv ~/.local/lib/code-server-3.7.4-linux-amd64 ~/.local/lib/code-server-3.7.4
-ln -s ~/.local/lib/code-server-3.7.4/bin/code-server ~/.local/bin/code-server
-PATH="~/.local/bin:$PATH"
-code-server
-# Now visit http://127.0.0.1:8080. Your password is in ~/.config/code-server/config.yaml
-```
-
-## Docker
-
-```bash
-# This will start a code-server container and expose it at http://127.0.0.1:8080.
-# It will also mount your current directory into the container as `/home/coder/project`
-# and forward your UID/GID so that all file system operations occur as your user outside
-# the container.
-#
-# Your $HOME/.config is mounted at $HOME/.config within the container to ensure you can
-# easily access/modify your code-server config in $HOME/.config/code-server/config.json
-# outside the container.
-mkdir -p ~/.config
-docker run -it --name code-server -p 127.0.0.1:8080:8080 \
- -v "$HOME/.config:/home/coder/.config" \
- -v "$PWD:/home/coder/project" \
- -u "$(id -u):$(id -g)" \
- -e "DOCKER_USER=$USER" \
- codercom/code-server:latest
-```
-
-Our official image supports `amd64` and `arm64`.
-
-For `arm32` support there is a popular community maintained alternative:
-
-https://hub.docker.com/r/linuxserver/code-server
-
-## helm
-
-See [the chart](../ci/helm-chart).
diff --git a/doc/ipad.md b/doc/ipad.md
deleted file mode 100644
index 0c2c60bb4def..000000000000
--- a/doc/ipad.md
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-# iPad
-
-- [Known Issues](#known-issues)
-- [How to access code-server with a self signed certificate on iPad?](#how-to-access-code-server-with-a-self-signed-certificate-on-ipad)
- - [Servediter iPad App](#servediter-ipad-app)
-
-
-
-## Known Issues
-
-- Getting self signed certificates certificates to work is involved, see below.
-- Keyboard may disappear sometimes [#1313](https://github.com/cdr/code-server/issues/1313), [#979](https://github.com/cdr/code-server/issues/979)
-- Trackpad scrolling does not work [#1455](https://github.com/cdr/code-server/issues/1455)
-- See [issues tagged with the iPad label](https://github.com/cdr/code-server/issues?q=is%3Aopen+is%3Aissue+label%3AiPad) for more.
-
-## How to access code-server with a self signed certificate on iPad?
-
-Accessing a self signed certificate on iPad isn't as easy as accepting through all
-the security warnings. Safari will prevent WebSocket connections unless the certificate
-is installed as a profile on the device.
-
-The below assumes you are using the self signed certificate that code-server
-generates for you. If not, that's fine but you'll have to make sure your certificate
-abides by the following guidelines from Apple: https://support.apple.com/en-us/HT210176
-
-**note**: Another undocumented requirement we noticed is that the certificate has to have `basicConstraints=CA:true`.
-
-The following instructions assume you have code-server installed and running
-with a self signed certificate. If not, please first go through [./guide.md](./guide.md)!
-
-**warning**: Your iPad must access code-server via a domain name. It could be local
-DNS like `mymacbookpro.local` but it must be a domain name. Otherwise Safari will
-refuse to allow WebSockets to connect.
-
-1. Your certificate **must** have a subject alt name that matches the hostname
- at which you will access code-server from your iPad. You can pass this to code-server
- so that it generates the certificate correctly with `--cert-host`.
-2. Share your self signed certificate with the iPad.
- - code-server will print the location of the certificate it has generated in the logs.
-
-```
-[2020-10-30T08:55:45.139Z] info - Using generated certificate and key for HTTPS: ~/.local/share/code-server/mymbp_local.crt
-```
-
-- You can mail it to yourself or if you have a Mac, it's easiest to just Airdrop to the iPad.
-
-3. When opening the `*.crt` file, you'll be prompted to go into settings to install.
-4. Go to `Settings -> General -> Profile`, select the profile and then hit `Install`.
- - It should say the profile is verified.
-5. Go to `Settings -> About -> Certificate Trust Settings` and enable full trust for
- the certificate.
-6. Now you can access code-server! 🍻
-
-### Servediter iPad App
-
-If you are unable to get the self signed certificate working or you do not have a domain
-name to use, you can use the Servediter iPad App instead!
-
-**note**: This is not an officially supported app by the code-server team!
-
-Download [Serveediter](https://apps.apple.com/us/app/servediter-for-code-server/id1504491325) from the
-App Store and then input your server information. If you are running a local server or mabye a usb-c
-connected Raspberry Pi, you will input your settings into "Self Hosted Server".
diff --git a/doc/npm.md b/doc/npm.md
deleted file mode 100644
index 4dd28e15774f..000000000000
--- a/doc/npm.md
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-# npm Install Requirements
-
-- [Ubuntu, Debian](#ubuntu-debian)
-- [Fedora, CentOS, RHEL](#fedora-centos-rhel)
-- [macOS](#macos)
-
-
-
-If you're installing the npm module you'll need certain dependencies to build
-the native modules used by VS Code.
-
-You also need at least node v12 installed. See [#1633](https://github.com/cdr/code-server/issues/1633).
-
-## Ubuntu, Debian
-
-```bash
-sudo apt-get install -y \
- build-essential \
- pkg-config \
- libx11-dev \
- libxkbfile-dev \
- libsecret-1-dev \
- python3
-npm config set python python3
-```
-
-## Fedora, CentOS, RHEL
-
-```bash
-sudo yum groupinstall -y 'Development Tools'
-sudo yum config-manager --set-enabled PowerTools # unnecessary on CentOS 7
-sudo yum install -y python2 libsecret-devel libX11-devel libxkbfile-devel
-npm config set python python2
-```
-
-## macOS
-
-```bash
-xcode-select --install
-```
diff --git a/doc/triage.md b/doc/triage.md
deleted file mode 100644
index e508df414c5e..000000000000
--- a/doc/triage.md
+++ /dev/null
@@ -1,37 +0,0 @@
-# Triage
-
-## Filter
-
-Triaging code-server issues is done with the following issue filter:
-
-```
-is:issue is:open no:project sort:created-asc -label:blocked -label:upstream -label:waiting-for-info -label:extension-request
-```
-
-This will show issues that:
-
-1. Are open.
-2. Have no assigned project.
-3. Are not `blocked` or tagged for work by `upstream` (VS Code core team)
- - If an upstream issue is detrimental to the code-server experience we may fix it in
- our patch instead of waiting for the VS Code team to fix it.
- - Someone should periodically go through these issues to see if they can be unblocked
- though!
-4. Are not in `waiting-for-info`.
-5. Are not extension requests.
-
-## Process
-
-1. If an issue is a question/discussion it should be converted into a GitHub discussion.
-2. Next, give the issue the appropriate labels and feel free to create new ones if
- necessary.
- - There are no hard and set rules for labels. We don't have many so look through and
- see how they've been used throughout the repository. They all also have descriptions.
-3. If more information is required, please ask the submitter and tag as
- `waiting-for-info` and wait.
-4. Finally, the issue should be moved into the
- [code-server](https://github.com/cdr/code-server/projects/1) project where we pick
- out issues to fix and track their progress.
-
-We also use [milestones](https://github.com/cdr/code-server/milestones) to track what
-issues are planned/or were closed for what release.
diff --git a/docs/CODE_OF_CONDUCT.md b/docs/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000000..168eac481bb7
--- /dev/null
+++ b/docs/CODE_OF_CONDUCT.md
@@ -0,0 +1,92 @@
+
+
+
+# Contributor Covenant Code of Conduct
+
+- [Contributor Covenant Code of Conduct](#contributor-covenant-code-of-conduct)
+ - [Our Pledge](#our-pledge)
+ - [Our Standards](#our-standards)
+ - [Our Responsibilities](#our-responsibilities)
+ - [Scope](#scope)
+ - [Enforcement](#enforcement)
+ - [Attribution](#attribution)
+
+
+
+
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, sex characteristics, gender identity and expression,
+level of experience, education, socio-economic status, nationality, personal
+appearance, race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+- Using welcoming and inclusive language
+- Being respectful of differing viewpoints and experiences
+- Gracefully accepting constructive criticism
+- Focusing on what is best for the community
+- Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+- The use of sexualized language or imagery and unwelcome sexual attention or
+ advances
+- Trolling, insulting/derogatory comments, and personal or political attacks
+- Public or private harassment
+- Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+- Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at opensource@coder.com. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+
+[homepage]: https://www.contributor-covenant.org
+
+For answers to common questions about this code of conduct, see
+https://www.contributor-covenant.org/faq
diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
new file mode 100644
index 000000000000..d857b20c3850
--- /dev/null
+++ b/docs/CONTRIBUTING.md
@@ -0,0 +1,288 @@
+
+
+
+# Contributing
+
+- [Requirements](#requirements)
+ - [Linux-specific requirements](#linux-specific-requirements)
+- [Development workflow](#development-workflow)
+ - [Version updates to Code](#version-updates-to-code)
+ - [Patching Code](#patching-code)
+ - [Build](#build)
+ - [Troubleshooting](#troubleshooting)
+ - [I see "Forbidden access" when I load code-server in the browser](#i-see-forbidden-access-when-i-load-code-server-in-the-browser)
+ - ["Can only have one anonymous define call per script"](#can-only-have-one-anonymous-define-call-per-script)
+ - [Help](#help)
+- [Test](#test)
+ - [Unit tests](#unit-tests)
+ - [Script tests](#script-tests)
+ - [Integration tests](#integration-tests)
+ - [End-to-end tests](#end-to-end-tests)
+- [Structure](#structure)
+ - [Modifications to Code](#modifications-to-code)
+ - [Currently Known Issues](#currently-known-issues)
+
+
+
+
+## Requirements
+
+The prerequisites for contributing to code-server are almost the same as those
+for [VS Code](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites).
+Here is what is needed:
+
+- `node` v24.x
+- `git` v2.x or greater
+- [`git-lfs`](https://git-lfs.github.com)
+- [`npm`](https://www.npmjs.com/)
+ - Used to install JS packages and run scripts
+- [`nfpm`](https://nfpm.goreleaser.com/)
+ - Used to build `.deb` and `.rpm` packages
+- [`jq`](https://stedolan.github.io/jq/)
+ - Used to build code-server releases
+- [`gnupg`](https://gnupg.org/index.html)
+ - All commits must be signed and verified; see GitHub's [Managing commit
+ signature
+ verification](https://docs.github.com/en/github/authenticating-to-github/managing-commit-signature-verification)
+ or follow [this tutorial](https://joeprevite.com/verify-commits-on-github)
+- `quilt`
+ - Used to manage patches to Code
+- `rsync` and `unzip`
+ - Used for code-server releases
+- `bats`
+ - Used to run script unit tests
+
+### Linux-specific requirements
+
+If you're developing code-server on Linux, make sure you have installed or
+install the following dependencies:
+
+```shell
+sudo apt-get install build-essential g++ libx11-dev libxkbfile-dev libsecret-1-dev libkrb5-dev python-is-python3
+```
+
+These are required by Code. See [their Wiki](https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites)
+for more information.
+
+## Development workflow
+
+1. `git clone https://github.com/coder/code-server.git` - Clone `code-server`
+2. `git submodule update --init` - Clone `vscode` submodule
+3. `quilt push -a` - Apply patches to the `vscode` submodule.
+4. `npm install` - Install dependencies
+5. `npm run watch` - Launch code-server localhost:8080. code-server will be live
+ reloaded when changes are made; the browser needs to be refreshed manually.
+
+When pulling down changes that include modifications to the patches you will
+need to apply them with `quilt`. If you pull down changes that update the
+`vscode` submodule you will need to run `git submodule update --init` and
+re-apply the patches.
+
+When you make a change that affects people deploying the marketplace please
+update the changelog as part of your PR.
+
+Note that building code-server takes a very, very long time, and loading it in
+the browser in development mode also takes a very, very long time.
+
+Display language (Spanish, etc) support only works in a full build; it will not
+work in development mode.
+
+Generally we prefer that PRs be squashed into `main` but you can rebase or merge
+if it is important to keep the individual commits (make sure to clean up the
+commits first if you are doing this).
+
+### Version updates to Code
+
+PRs will be automatically created with updates to VS Code. If a patch cannot be
+automatically resolved, it will be necessary to clone the branch, resolve the
+conflicts manually, and finish the update. To do this:
+
+1. Apply as many patches as possible `quilt push -a`.
+2. Once you hit a conflict, force apply with `quilt push -f`, manually add back
+ the rejected code, then run `quilt refresh`.
+3. Once all patches have been resolved, run `./ci/build/update.sh` to finish the
+ update process.
+4. Commit all changes, push them up to the branch, and update the checklist in
+ the PR description.
+
+Once the PR is ready, manually verify that the unreleased changelog section
+contains all the changes going into this version before merging.
+
+### Patching Code
+
+1. You can go through the patch stack with `quilt push` and `quilt pop`.
+2. Create a new patch (`quilt new {name}.diff`) or use an existing patch.
+3. Add the file(s) you are patching (`quilt add [-P patch] {file}`). A file
+ **must** be added before you make changes to it.
+4. Make your changes. Patches do not need to be independent of each other but
+ each patch must result in a working code-server without any broken in-between
+ states otherwise they are difficult to test and modify.
+5. Add your changes to the patch (`quilt refresh`)
+6. Add a comment in the patch about the reason for the patch and how to
+ reproduce the behavior it fixes or adds. Every patch should have an e2e test
+ as well.
+
+### Build
+
+You can build a full production release as follows:
+
+```shell
+git submodule update --init
+quilt push -a
+npm install
+npm run build
+VERSION=0.0.0 npm run build:vscode
+KEEP_MODULES=1 npm run release
+```
+
+You can omit `KEEP_MODULES` if you intend to use this in a platform-agnostic way
+(like for publishing to NPM), but since the VS Code build process does
+post-processing deletion of the modules, it is recommended to keep the modules
+when possible, since if you install them later you will have more than is
+required. `KEEP_MODULES` will also bundle Node and the code-server entry script.
+
+Run your build:
+
+```shell
+./release/bin/code-server
+```
+
+Or if you omitted `KEEP_MODULES`:
+
+```shell
+cd release
+npm install --omit=dev
+node .
+```
+
+Then, to package the release:
+
+```shell
+npm run package
+```
+
+> On Linux, the currently running distro will become the minimum supported
+> version. In our GitHub Actions CI, we use CentOS 8 for maximum compatibility.
+> If you need your builds to support older distros, run the build commands
+> inside a Docker container with all the build requirements installed.
+
+### Troubleshooting
+
+#### I see "Forbidden access" when I load code-server in the browser
+
+This means your patches didn't apply correctly. We have a patch to remove the
+auth from vanilla Code because we use our own.
+
+Try popping off the patches with `quilt pop -a` and reapplying with `quilt push
+-a`.
+
+#### "Can only have one anonymous define call per script"
+
+Code might be trying to use a dev or prod HTML in the wrong context. You can try
+re-running code-server and setting `VSCODE_DEV=1`.
+
+### Help
+
+If you get stuck or need help, you can always start a new GitHub Discussion
+[here](https://github.com/coder/code-server/discussions). One of the maintainers
+will respond and help you out.
+
+## Test
+
+There are four kinds of tests in code-server:
+
+1. Unit tests
+2. Script tests
+3. Integration tests
+4. End-to-end tests
+
+### Unit tests
+
+Our unit tests are written in TypeScript and run using
+[Jest](https://jestjs.io/), the testing framework].
+
+These live under [test/unit](../test/unit).
+
+We use unit tests for functions and things that can be tested in isolation. The
+file structure is modeled closely after `/src` so it's easy for people to know
+where test files should live.
+
+### Script tests
+
+Our script tests are written in bash and run using [bats](https://github.com/bats-core/bats-core).
+
+These tests live under `test/scripts`.
+
+We use these to test anything related to our scripts (most of which live under
+`ci`).
+
+### Integration tests
+
+These are a work in progress. We build code-server and run tests with `npm run
+test:integration`, which ensures that code-server builds work on their
+respective platforms.
+
+Our integration tests look at components that rely on one another. For example,
+testing the CLI requires us to build and package code-server.
+
+### End-to-end tests
+
+The end-to-end (e2e) tests are written in TypeScript and run using
+[Playwright](https://playwright.dev/).
+
+These live under [test/e2e](../test/e2e).
+
+Before the e2e tests run, we run `globalSetup`, which eliminates the need to log
+in before each test by preserving the authentication state.
+
+Take a look at `codeServer.test.ts` to see how you would use it (see
+`test.use`).
+
+We also have a model where you can create helpers to use within tests. See
+[models/CodeServer.ts](../test/e2e/models/CodeServer.ts) for an example.
+
+## Structure
+
+code-server essentially serves as an HTTP API for logging in and starting a
+remote Code process.
+
+The CLI code is in [src/node](../src/node) and the HTTP routes are implemented
+in [src/node/routes](../src/node/routes).
+
+Most of the meaty parts are in the Code portion of the codebase under
+[lib/vscode](../lib/vscode), which we describe next.
+
+### Modifications to Code
+
+Our modifications to Code can be found in the [patches](../patches) directory.
+We pull in Code as a submodule pointing to an upstream release branch.
+
+In v1 of code-server, we had Code as a submodule and used a single massive patch
+that split the codebase into a front-end and a server. The front-end consisted
+of the UI code, while the server ran the extensions and exposed an API to the
+front-end for file access and all UI needs.
+
+Over time, Microsoft added support to Code to run it on the web. They had made
+the front-end open source, but not the server. As such, code-server v2 (and
+later) uses the Code front-end and implements the server. We did this by using a
+Git subtree to fork and modify Code.
+
+Microsoft eventually made the server open source and we were able to reduce our
+changes significantly. Some time later we moved back to a submodule and patches
+(managed by `quilt` this time instead of the mega-patch).
+
+As the web portion of Code continues to mature, we'll be able to shrink and
+possibly eliminate our patches. In the meantime, upgrading the Code version
+requires us to ensure that our changes are still applied correctly and work as
+intended. In the future, we'd like to run Code unit tests against our builds to
+ensure that features work as expected.
+
+> We have [extension docs](../ci/README.md) on the CI and build system.
+
+If the functionality you're working on does NOT depend on code from Code, please
+move it out and into code-server.
+
+### Currently Known Issues
+
+- Creating custom Code extensions and debugging them doesn't work
+- Extension profiling and tips are currently disabled
diff --git a/docs/FAQ.md b/docs/FAQ.md
new file mode 100644
index 000000000000..656b45978fe3
--- /dev/null
+++ b/docs/FAQ.md
@@ -0,0 +1,562 @@
+
+
+
+# FAQ
+
+- [Questions?](#questions)
+- [How should I expose code-server to the internet?](#how-should-i-expose-code-server-to-the-internet)
+- [Can I use code-server on the iPad?](#can-i-use-code-server-on-the-ipad)
+- [How does the config file work?](#how-does-the-config-file-work)
+- [How do I make my keyboard shortcuts work?](#how-do-i-make-my-keyboard-shortcuts-work)
+- [Why can't code-server use Microsoft's extension marketplace?](#why-cant-code-server-use-microsofts-extension-marketplace)
+- [How can I request an extension that's missing from the marketplace?](#how-can-i-request-an-extension-thats-missing-from-the-marketplace)
+- [How do I install an extension?](#how-do-i-install-an-extension)
+- [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)
+- [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 does code-server decide what workspace or folder to open?](#how-does-code-server-decide-what-workspace-or-folder-to-open)
+- [Can I open a file at a specific line from a URL?](#can-i-open-a-file-at-a-specific-line-from-a-url)
+- [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 direct server-side requests through a proxy?](#how-do-i-direct-server-side-requests-through-a-proxy)
+- [How do I debug issues with code-server?](#how-do-i-debug-issues-with-code-server)
+- [What is the healthz endpoint?](#what-is-the-healthz-endpoint)
+- [What is the heartbeat file?](#what-is-the-heartbeat-file)
+- [How do I change the reconnection grace time?](#how-do-i-change-the-reconnection-grace-time)
+- [How do I change the password?](#how-do-i-change-the-password)
+- [Can I store my password hashed?](#can-i-store-my-password-hashed)
+- [Is multi-tenancy possible?](#is-multi-tenancy-possible)
+- [Can I use Docker in a code-server container?](#can-i-use-docker-in-a-code-server-container)
+- [How do I disable telemetry?](#how-do-i-disable-telemetry)
+- [What's the difference between code-server and Coder?](#whats-the-difference-between-code-server-and-coder)
+- [What's the difference between code-server and Theia?](#whats-the-difference-between-code-server-and-theia)
+- [What's the difference between code-server and OpenVSCode-Server?](#whats-the-difference-between-code-server-and-openvscode-server)
+- [What's the difference between code-server and GitHub Codespaces?](#whats-the-difference-between-code-server-and-github-codespaces)
+- [What's the difference between code-server and VS Code web?](#whats-the-difference-between-code-server-and-vs-code-web)
+- [Does code-server have any security login validation?](#does-code-server-have-any-security-login-validation)
+- [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 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)
+- [Why do web views not work?](#why-do-web-views-not-work)
+
+
+
+
+## Questions?
+
+Please file all questions and support requests at
+.
+
+## How should I expose code-server to the internet?
+
+Please see [our instructions on exposing code-server safely to the
+internet](./guide.md).
+
+## Can I use code-server on the iPad?
+
+See [iPad](./ipad.md) for information on using code-server on the iPad.
+
+## How does the config file work?
+
+When `code-server` starts up, it creates a default config file in `~/.config/code-server/config.yaml`:
+
+```yaml
+bind-addr: 127.0.0.1:8080
+auth: password
+password: mew...22 # Randomly generated for each config.yaml
+cert: false
+```
+
+The default config defines the following behavior:
+
+- Listen on the loopback IP port 8080
+- Enable password authorization
+- Do not use TLS
+
+Each key in the file maps directly to a `code-server` flag (run `code-server --help` to see a listing of all the flags). Any flags passed to `code-server`
+will take priority over the config file.
+
+You can change the config file's location using the `--config` flag or
+`$CODE_SERVER_CONFIG` environment variable.
+
+The default location respects `$XDG_CONFIG_HOME`.
+
+## How do I make my keyboard shortcuts work?
+
+Many shortcuts will not work by default, since they'll be "caught" by the browser.
+
+If you use Chrome, you can work around this by installing the progressive web
+app (PWA):
+
+1. Start the editor
+2. Click the **plus** icon in the URL toolbar to install the PWA
+
+If you use Firefox, you can use the appropriate extension to install PWA.
+
+1. Go to the installation [website](https://addons.mozilla.org/en-US/firefox/addon/pwas-for-firefox/) of the add-on
+2. Add the add-on to Firefox
+3. Follow the os-specific instructions on how to install the runtime counterpart
+
+For other browsers, you'll have to remap keybindings for shortcuts to work.
+
+## Why can't code-server use Microsoft's extension marketplace?
+
+Though code-server takes the open-source core of VS Code and allows you to run
+it in the browser, it is not entirely equivalent to Microsoft's VS Code.
+
+One major difference is in regards to extensions and the marketplace. The core
+of VS code is open source, while the marketplace and many published Microsoft
+extensions are not. Furthermore, Microsoft prohibits the use of any
+non-Microsoft VS Code from accessing their marketplace. Per the [Terms of
+Service](https://cdn.vsassets.io/v/M146_20190123.39/_content/Microsoft-Visual-Studio-Marketplace-Terms-of-Use.pdf):
+
+> Marketplace Offerings are intended for use only with Visual Studio Products
+> and Services, and you may only install and use Marketplace Offerings with
+> Visual Studio Products and Services.
+
+Because of this, we can't offer any extensions on Microsoft's marketplace.
+Instead, we use the [Open-VSX extension gallery](https://open-vsx.org), which is also used by various other forks.
+It isn't perfect, but its getting better by the day with more and more extensions.
+
+We also offer our own marketplace for open source extensions, but plan to
+deprecate it at a future date and completely migrate to Open-VSX.
+
+These are the closed-source extensions that are presently unavailable:
+
+1. [Live Share](https://visualstudio.microsoft.com/services/live-share). We may
+ implement something similar (see
+ [#33](https://github.com/coder/code-server/issues/33))
+1. [Remote Extensions (SSH, Containers,
+ WSL)](https://github.com/microsoft/vscode-remote-release). We may implement
+ these again at some point, see
+ ([#1315](https://github.com/coder/code-server/issues/1315)).
+
+For more about the closed source portions of VS Code, see [vscodium/vscodium](https://github.com/VSCodium/vscodium#why-does-this-exist).
+
+## How can I request an extension that's missing from the marketplace?
+
+To add an extension to Open-VSX, please see [open-vsx/publish-extensions](https://github.com/open-vsx/publish-extensions).
+We no longer plan to add new extensions to our legacy extension gallery.
+
+## How do I install an extension?
+
+You can install extensions from the marketplace using the extensions sidebar in
+code-server or from the command line:
+
+```console
+code-server --install-extension
+# example: code-server --install-extension wesbos.theme-cobalt2
+
+# From the Coder extension marketplace
+code-server --install-extension ms-python.python
+
+# From a downloaded VSIX on the file system
+code-server --install-extension downloaded-ms-python.python.vsix
+```
+
+## How do I install an extension manually?
+
+If there's an extension unavailable in the marketplace or an extension that
+doesn't work, you can download the VSIX from its GitHub releases or build it
+yourself.
+
+Once you have downloaded the VSIX to the remote machine, you can either:
+
+- Run the **Extensions: Install from VSIX** command in the Command Palette.
+- Run `code-server --install-extension ` in the terminal
+
+You can also download extensions using the command line. For instance,
+downloading from OpenVSX can be done like this:
+
+```shell
+code-server --install-extension
+```
+
+## How do I use my own extensions marketplace?
+
+If you own a marketplace that implements the VS Code Extension Gallery API, you
+can point code-server to it by setting `$EXTENSIONS_GALLERY`.
+This corresponds directly with the `extensionsGallery` entry in in VS Code's `product.json`.
+
+For example:
+
+```bash
+export EXTENSIONS_GALLERY='{"serviceUrl": "https://my-extensions/api"}'
+```
+
+Though you can technically use Microsoft's marketplace in this manner, we
+strongly discourage you from doing so since this is [against their Terms of Use](#why-cant-code-server-use-microsofts-extension-marketplace).
+
+For further information, see [this
+discussion](https://github.com/microsoft/vscode/issues/31168#issue-244533026)
+regarding the use of the Microsoft URLs in forks, as well as [VSCodium's
+docs](https://github.com/VSCodium/vscodium/blob/master/DOCS.md#extensions--marketplace).
+
+## Where are extensions stored?
+
+Extensions are stored in `~/.local/share/code-server/extensions` by default.
+
+On Linux and macOS if you set the `XDG_DATA_HOME` environment variable, the
+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?
+
+You can use the [Settings
+Sync](https://marketplace.visualstudio.com/items?itemName=Shan.code-settings-sync)
+extension for this purpose.
+
+Alternatively, you can also pass `--user-data-dir ~/.vscode` or copy `~/.vscode`
+into `~/.local/share/code-server` to reuse your existing VS Code extensions and
+configuration.
+
+## How does code-server decide what workspace or folder to open?
+
+code-server tries the following in this order:
+
+1. The `workspace` query parameter
+2. The `folder` query parameter
+3. The workspace or directory passed via the command line
+4. The last opened workspace or directory
+
+## Can I open a file at a specific line from a URL?
+
+Yes. In addition to `workspace` and `folder`, code-server supports VS Code's
+`payload` query parameter, which can open a specific file — optionally at a
+line and column — once the workbench loads.
+
+`payload` is a URL-encoded JSON array of `[key, value]` string pairs. The
+`openFile` key takes a `vscode-remote:///` URI, where
+`` is the host you use to reach code-server. Add
+`["gotoLineMode","true"]` to have a trailing `:line[:column]` suffix on the
+path interpreted as a cursor position:
+
+```text
+https://code.example.com/?folder=/home/coder/project&payload=[["gotoLineMode","true"],["openFile","vscode-remote://code.example.com/home/coder/project/src/app.py:10:5"]]
+```
+
+(with the `payload` value URL-encoded). Notes:
+
+- Paths must be absolute; there is no form relative to `folder`.
+- This is upstream VS Code web behavior (the same mechanism vscode.dev uses),
+ so it works without any code-server-specific configuration.
+
+For example, to generate links from a shell:
+
+```sh
+#!/bin/sh
+# usage: code-link [line[:column]]
+HOST=code.example.com
+payload="[[\"gotoLineMode\",\"true\"],[\"openFile\",\"vscode-remote://$HOST$1${2:+:$2}\"]]"
+printf 'https://%s/?folder=%s&payload=%s\n' "$HOST" "$(dirname "$1")" \
+ "$(printf '%s' "$payload" | jq -sRr @uri)"
+```
+
+## How do I access my Documents/Downloads/Desktop folders in code-server on macOS?
+
+Newer versions of macOS require permission through a non-UNIX mechanism for
+code-server to access the Desktop, Documents, Pictures, Downloads, and other folders.
+
+You may have to give Node.js full disk access, since it doesn't implement any of the macOS permission request features natively:
+
+1. Find where Node.js is installed on your machine
+
+ ```console
+ $ which node
+ /usr/local/bin/node
+ ```
+
+2. Grant Node.js full disk access. Open **System Preferences** > **Security &
+ Privacy** > **Privacy** > **Full Disk Access**. Then, click the 🔒 to unlock,
+ click **+**, and select the Node.js binary you located in the previous step.
+
+See [#2794](https://github.com/coder/code-server/issues/2794) for additional context.
+
+## How do I direct server-side requests through a proxy?
+
+> code-server proxies only server-side requests.
+
+To direct server-side requests through a proxy, code-server supports the
+following environment variables:
+
+- `$HTTP_PROXY`
+- `$HTTPS_PROXY`
+- `$NO_PROXY`
+
+```sh
+export HTTP_PROXY=https://134.8.5.4
+export HTTPS_PROXY=https://134.8.5.4
+# Now all of code-server's server side requests will go through
+# https://134.8.5.4 first.
+code-server
+```
+
+- See
+ [proxy-from-env](https://www.npmjs.com/package/proxy-from-env#environment-variables)
+ for a detailed reference on these environment variables and their syntax (note
+ that code-server only uses the `http` and `https` protocols).
+- See [proxy-agent](https://www.npmjs.com/package/proxy-agent) for information
+ on on the supported proxy protocols.
+
+## How do I debug issues with code-server?
+
+First, run code-server with the `debug` logging (or `trace` to be really
+thorough) by setting the `--log` flag or the `LOG_LEVEL` environment variable.
+`-vvv` and `--verbose` are aliases for `--log trace`.
+
+First, run code-server with `debug` logging (or `trace` logging for more
+thorough messages) by setting the `--log` flag or the `LOG_LEVEL` environment
+variable.
+
+```text
+code-server --log debug
+```
+
+> Note that the `-vvv` and `--verbose` flags are aliases for `--log trace`.
+
+Next, replicate the issue you're having so that you can collect logging
+information from the following places:
+
+1. The most recent files from `~/.local/share/code-server/coder-logs`
+2. The browser console
+3. The browser network tab
+
+Additionally, collecting core dumps (you may need to enable them first) if
+code-server crashes can be helpful.
+
+## What is the healthz endpoint?
+
+You can use the `/healthz` endpoint exposed by code-server to check whether
+code-server is running without triggering a heartbeat. The response includes a
+status (e.g., `alive` or `expired`) and a timestamp for the last heartbeat
+(the default is `0`).
+
+```json
+{
+ "status": "alive",
+ "lastHeartbeat": 1599166210566
+}
+```
+
+This endpoint doesn't require authentication.
+
+## What is the heartbeat file?
+
+As long as there is an active browser connection, code-server touches
+`~/.local/share/code-server/heartbeat` once a minute.
+
+If you want to shutdown code-server if there hasn't been an active connection
+after a predetermined amount of time, you can use the --idle-timeout-seconds flag
+or set an `CODE_SERVER_IDLE_TIMEOUT_SECONDS` environment variable.
+
+## How do I change the reconnection grace time?
+
+Pass `--reconnection-grace-time ` to `code-server`, set
+`CODE_SERVER_RECONNECTION_GRACE_TIME=`, or add
+`reconnection-grace-time: ` to
+`~/.config/code-server/config.yaml`.
+
+The default is `10800` (3 hours). If a client stays disconnected longer than
+this, it must reload the window.
+
+## How do I change the password?
+
+Edit the `password` field in the code-server config file at
+`~/.config/code-server/config.yaml`, then restart code-server:
+
+```bash
+sudo systemctl restart code-server@$USER
+```
+
+## Can I store my password hashed?
+
+Yes, you can do so by setting the value of `hashed-password` instead of `password`. Generate the hash with:
+
+```shell
+echo -n "thisismypassword" | npx argon2-cli -e
+$argon2i$v=19$m=4096,t=3,p=1$wst5qhbgk2lu1ih4dmuxvg$ls1alrvdiwtvzhwnzcm1dugg+5dto3dt1d5v9xtlws4
+```
+
+Replace `thisismypassword` with your actual password and **remember to put it
+inside quotes**! For example:
+
+```yaml
+auth: password
+hashed-password: "$argon2i$v=19$m=4096,t=3,p=1$wST5QhBgk2lu1ih4DMuxvg$LS1alrVdIWtvZHwnzCM1DUGg+5DTO3Dt1d5v9XtLws4"
+```
+
+The `hashed-password` field takes precedence over `password`.
+
+If you're using Docker Compose file, in order to make this work, you need to change all the single $ to $$. For example:
+
+```yaml
+- HASHED_PASSWORD=$$argon2i$$v=19$$m=4096,t=3,p=1$$wST5QhBgk2lu1ih4DMuxvg$$LS1alrVdIWtvZHwnzCM1DUGg+5DTO3Dt1d5v9XtLws4
+```
+
+## Is multi-tenancy possible?
+
+If you want to run multiple code-servers on shared infrastructure, we recommend
+using virtual machines (provide one VM per user). This will easily allow users
+to run a Docker daemon. If you want to use Kubernetes, you'll want to
+use [kubevirt](https://kubevirt.io) or
+[sysbox](https://github.com/nestybox/sysbox) to give each user a VM-like
+experience instead of just a container.
+
+## Can I use Docker in a code-server container?
+
+If you'd like to access Docker inside of code-server, mount the Docker socket in
+from `/var/run/docker.sock`. Then, install the Docker CLI in the code-server
+container, and you should be able to access the daemon.
+
+You can even make volume mounts work. Let's say you want to run a container and
+mount into `/home/coder/myproject` from inside the `code-server` container. You
+need to make sure the Docker daemon's `/home/coder/myproject` is the same as the
+one mounted inside the `code-server` container, and the mount will work.
+
+If you want Docker enabled when deploying on Kubernetes, look at the `values.yaml`
+file for the 3 fields: `extraVars`, `lifecycle.postStart`, and `extraContainers`.
+
+## How do I disable telemetry?
+
+Use the `--disable-telemetry` flag to disable telemetry.
+
+> We use the data collected only to improve code-server.
+
+## What's the difference between code-server and Coder?
+
+code-server and Coder are both applications that can be installed on any
+machine. The main difference is who they serve. Out of the box, code-server is
+simply VS Code in the browser while Coder is a tool for provisioning remote
+development environments via Terraform.
+
+code-server was built for individuals while Coder was built for teams. In Coder, you create Workspaces which can have applications like code-server. If you're looking for a team solution, you should reach for [Coder](https://github.com/coder/coder).
+
+## What's the difference between code-server and Theia?
+
+At a high level, code-server is a patched fork of VS Code that runs in the
+browser whereas Theia takes some parts of VS Code but is an entirely different
+editor.
+
+[Theia](https://github.com/eclipse-theia/theia) is a browser IDE loosely based
+on VS Code. It uses the same text editor library
+([Monaco](https://github.com/Microsoft/monaco-editor)) and extension API, but
+everything else is different. Theia also uses [Open VSX](https://open-vsx.org)
+for extensions.
+
+Theia doesn't allow you to reuse your existing VS Code config.
+
+## What's the difference between code-server and OpenVSCode-Server?
+
+code-server and OpenVSCode-Server both allow you to access VS Code via a
+browser. OpenVSCode-Server is a direct fork of VS Code with changes comitted
+directly while code-server pulls VS Code in via a submodule and makes changes
+via patch files.
+
+However, OpenVSCode-Server is scoped at only making VS Code available as-is in
+the web browser. code-server contains additional changes to make the self-hosted
+experience better (see the next section for details).
+
+## What's the difference between code-server and GitHub Codespaces?
+
+Both code-server and GitHub Codespaces allow you to access VS Code via a
+browser. GitHub Codespaces, however, is a closed-source, paid service offered by
+GitHub and Microsoft.
+
+On the other hand, code-server is self-hosted, free, open-source, and can be run
+on any machine with few limitations.
+
+Specific changes include:
+
+- Password authentication
+- The ability to host at sub-paths
+- Self-contained web views that do not call out to Microsoft's servers
+- The ability to use your own marketplace and collect your own telemetry
+- Built-in proxy for accessing ports on the remote machine integrated into
+ VS Code's ports panel
+- Settings are stored on disk like desktop VS Code, instead of in browser
+ storage (note that state is still stored in browser storage).
+- Wrapper process that spawns VS Code on-demand and has a separate CLI
+- Notification when updates are available
+- [Some other things](https://github.com/coder/code-server/tree/main/patches)
+
+Some of these changes appear very unlikely to ever be adopted by Microsoft.
+Some may make their way upstream, further closing the gap, but at the moment it
+looks like there will always be some subtle differences.
+
+## What's the difference between code-server and VS Code web?
+
+VS Code web (which can be ran using `code serve-web`) has the same differences
+as the Codespaces section above. VS Code web can be a better choice if you need
+access to the official Microsoft marketplace.
+
+## Does code-server have any security login validation?
+
+code-server supports setting a single password and limits logins to two per
+minute plus an additional twelve per hour.
+
+## Are there community projects involving code-server?
+
+Visit the [awesome-code-server](https://github.com/coder/awesome-code-server)
+repository to view community projects and guides with code-server! Feel free to
+add your own!
+
+## How do I change the port?
+
+There are two ways to change the port on which code-server runs:
+
+1. with an environment variable e.g. `PORT=3000 code-server`
+2. using the flag `--bind-addr` e.g. `code-server --bind-addr localhost:3000`
+
+## How do I hide the coder/coder promotion in Help: Getting Started?
+
+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
+`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?
+
+You can pass the flag `--disable-file-downloads` to `code-server`
+
+## Why do web views not work?
+
+Web views rely on service workers, and service workers are only available in a
+secure context, so most likely the answer is that you are using an insecure
+context (for example an IP address).
+
+If this happens, in the browser log you will see something like:
+
+> Error loading webview: Error: Could not register service workers: SecurityError: Failed to register a ServiceWorker for scope with script: An SSL certificate error occurred when fetching the script..
+
+To fix this, you must either:
+
+- Access over localhost/127.0.0.1 which is always considered secure.
+- Use a domain with a real certificate (for example with Let's Encrypt).
+- Use a trusted self-signed certificate with [mkcert](https://mkcert.dev) (or
+ create and trust a certificate manually).
+- Disable security if your browser allows it. For example, in Chromium see
+ `chrome://flags/#unsafely-treat-insecure-origin-as-secure`
diff --git a/docs/MAINTAINING.md b/docs/MAINTAINING.md
new file mode 100644
index 000000000000..69263576ec2c
--- /dev/null
+++ b/docs/MAINTAINING.md
@@ -0,0 +1,112 @@
+
+
+
+# Maintaining
+
+- [Releasing](#releasing)
+ - [Release Candidates](#release-candidates)
+ - [AUR](#aur)
+ - [Docker](#docker)
+ - [nixpkgs](#nixpkgs)
+ - [npm](#npm)
+- [Testing](#testing)
+- [Documentation](#documentation)
+ - [Troubleshooting](#troubleshooting)
+
+
+
+
+We keep code-server up to date with VS Code releases (there are usually two or
+three a month) but we are not generally actively developing code-server aside
+from fixing regressions.
+
+Most of the work is keeping on top of issues and discussions.
+
+## Releasing
+
+1. Check that the changelog lists all the important changes.
+2. Make sure the changelog entry lists the current version of VS Code.
+3. Go to GitHub Actions > Draft release > Run workflow on the commit you want to
+ release. For the version we match VS Code's minor and patch version. The
+ patch number may become temporarily out of sync if we need to put out a
+ patch, but if we make our own minor change then we will not release it until
+ the next minor VS Code release.
+4. CI will build an NPM package and platform-specific packages, and upload those
+ to a draft release.
+5. Update the resulting draft release with the changelog contents.
+6. Publish the draft release after validating it.
+7. Update the changelog with the release date and bump the Helm chart version
+ once the Docker images have published.
+8. Merge the PR submitted to coder/code-server-aur repo.
+
+#### Release Candidates
+
+We prefer to do release candidates so the community can test things before a
+full-blown release. To do this follow the same steps as above but:
+
+1. Add a `-rc.` suffix to the version.
+2. When you publish the release select "pre-release". CI will not automatically
+ publish pre-releases.
+3. Do not update the chart version or merge in the changelog until the final
+ release.
+
+#### AUR
+
+We publish to AUR as a package
+[here](https://aur.archlinux.org/packages/code-server/). This process is manual
+and can be done by following the steps in [this
+repo](https://github.com/coder/code-server-aur).
+
+#### Docker
+
+We publish code-server as a Docker image
+[here](https://hub.docker.com/r/codercom/code-server), tagging it both with the
+version and latest.
+
+This is currently automated with the release process.
+
+#### nixpkgs
+
+We publish code-server in nixpkgs but it must be updated manually.
+
+#### npm
+
+We publish code-server as a npm package
+[here](https://www.npmjs.com/package/code-server/v/latest).
+
+This is currently automated with the release process.
+
+## Testing
+
+Our testing structure is laid out under our [Contributing
+docs](https://coder.com/docs/code-server/latest/CONTRIBUTING#test).
+
+If you're ever looking to add more tests, here are a few ways to get started:
+
+- run `npm run test:unit` and look at the coverage chart. You'll see all the
+ uncovered lines. This is a good place to start.
+- look at `test/scripts` to see which scripts are tested. We can always use more
+ tests there.
+- look at `test/e2e`. We can always use more end-to-end tests.
+
+Otherwise, talk to a current maintainer and ask which part of the codebase is
+lacking most when it comes to tests.
+
+## Documentation
+
+### Troubleshooting
+
+Our docs are hosted on [Vercel](https://vercel.com/). Vercel only shows logs in
+realtime, which means you need to have the logs open in one tab and reproduce
+your error in another tab. Since our logs are private to Coder the organization,
+you can only follow these steps if you're a Coder employee. Ask a maintainer for
+help if you need it.
+
+Taking a real scenario, let's say you wanted to troubleshoot [this docs
+change](https://github.com/coder/code-server/pull/4042). Here is how you would
+do it:
+
+1. Go to https://vercel.com/codercom/codercom
+2. Click "View Function Logs"
+3. In a separate tab, open the preview link from github-actions-bot
+4. Now look at the function logs and see if there are errors in the logs
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 000000000000..470095071afd
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,82 @@
+# code-server
+
+[](https://github.com/coder/code-server/discussions) [](https://coder.com/community) [](https://twitter.com/coderhq) [](https://discord.com/invite/coder) [](https://codecov.io/gh/coder/code-server) [](https://coder.com/docs/code-server/latest)
+
+Run [VS Code](https://github.com/Microsoft/vscode) on any machine anywhere and
+access it in the browser.
+
+
+
+
+## Highlights
+
+- Code on any device with a consistent development environment
+- Use cloud servers to speed up tests, compilations, downloads, and more
+- Preserve battery life when you're on the go; all intensive tasks run on your
+ server
+
+## Requirements
+
+See [requirements](https://coder.com/docs/code-server/latest/requirements) for minimum specs, as well as instructions
+on how to set up a Google VM on which you can install code-server.
+
+**TL;DR:** Linux machine with WebSockets enabled, 1 GB RAM, and 2 vCPUs
+
+## Getting started
+
+There are five ways to get started:
+
+1. Using the [install
+ script](https://github.com/coder/code-server/blob/main/install.sh), which
+ automates most of the process. The script uses the system package manager if
+ possible.
+2. Manually [installing
+ code-server](https://coder.com/docs/code-server/latest/install)
+3. Deploy code-server to your team with [coder/coder](https://cdr.co/coder-github)
+4. Using our one-click buttons and guides to [deploy code-server to a cloud
+ provider](https://github.com/coder/deploy-code-server) ⚡
+5. Using the [code-server feature for
+ devcontainers](https://github.com/coder/devcontainer-features/blob/main/src/code-server/README.md),
+ if you already use devcontainers in your project.
+
+If you use the install script, you can preview what occurs during the install
+process:
+
+```bash
+curl -fsSL https://code-server.dev/install.sh | sh -s -- --dry-run
+```
+
+To install, run:
+
+```bash
+curl -fsSL https://code-server.dev/install.sh | sh
+```
+
+When done, the install script prints out instructions for running and starting
+code-server.
+
+> **Note**
+> To manage code-server for a team on your infrastructure, see: [coder/coder](https://cdr.co/coder-github)
+
+We also have an in-depth [setup and
+configuration](https://coder.com/docs/code-server/latest/guide) guide.
+
+## Questions?
+
+See answers to [frequently asked
+questions](https://coder.com/docs/code-server/latest/FAQ).
+
+## Want to help?
+
+See [Contributing](https://coder.com/docs/code-server/latest/CONTRIBUTING) for
+details.
+
+## Hiring
+
+Interested in [working at Coder](https://coder.com/careers)? Check out [our open
+positions](https://coder.com/careers#openings)!
+
+## For Teams
+
+We develop [coder/coder](https://cdr.co/coder-github) to help teams to
+adopt remote development.
diff --git a/docs/SECURITY.md b/docs/SECURITY.md
new file mode 100644
index 000000000000..9ff33e365c4b
--- /dev/null
+++ b/docs/SECURITY.md
@@ -0,0 +1,33 @@
+# Security Policy
+
+Coder and the code-server team want to keep the code-server project secure and safe for end-users.
+
+## Tools
+
+We use the following tools to help us stay on top of vulnerability mitigation.
+
+- [dependabot](https://dependabot.com/)
+ - Submits pull requests to upgrade dependencies. We use dependabot's version
+ upgrades as well as security updates.
+- code-scanning
+ - [CodeQL](https://securitylab.github.com/tools/codeql/)
+ - Semantic code analysis engine that runs on a regular schedule (see
+ `codeql-analysis.yml`)
+ - [trivy](https://github.com/aquasecurity/trivy)
+ - Comprehensive vulnerability scanner that runs on PRs into the default
+ branch and scans both our container image and repository code (see
+ `trivy-scan-repo` and `trivy-scan-image` jobs in `build.yaml`)
+- `npm audit`
+ - Audits NPM dependencies.
+
+## Supported Versions
+
+Coder sponsors the development and maintenance of the code-server project. We will fix security issues within 90 days of receiving a report and publish the fix in a subsequent release. The code-server project does not provide backports or patch releases for security issues at this time.
+
+| Version | Supported |
+| ------------------------------------------------------- | ------------------ |
+| [Latest](https://github.com/coder/code-server/releases) | :white_check_mark: |
+
+## Reporting a Vulnerability
+
+To report a vulnerability, please send an email to security[@]coder.com, and our security team will respond to you.
diff --git a/docs/android.md b/docs/android.md
new file mode 100644
index 000000000000..4541bc7b5fee
--- /dev/null
+++ b/docs/android.md
@@ -0,0 +1,31 @@
+# Running code-server using UserLAnd
+
+1. Install UserLAnd from [Google Play](https://play.google.com/store/apps/details?id=tech.ula&hl=en_US&gl=US)
+2. Install an Ubuntu VM
+3. Start app
+4. Install Node.js and `curl` using `sudo apt install nodejs npm curl -y`
+5. Install `nvm`:
+
+```shell
+curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
+```
+
+6. Exit the terminal using `exit` and then reopen the terminal
+7. Install and use Node.js 24:
+
+```shell
+nvm install 24
+nvm use 24
+```
+
+8. Install code-server globally on device with: `npm install --global code-server`
+9. Run code-server with `code-server`
+10. Access on localhost:8080 in your browser
+
+# Running code-server using Nix-on-Droid
+
+1. Install Nix-on-Droid from [F-Droid](https://f-droid.org/packages/com.termux.nix/)
+2. Start app
+3. Spawn a shell with code-server by running `nix-shell -p code-server`
+4. Run code-server with `code-server`
+5. Access on localhost:8080 in your browser
diff --git a/docs/assets/images/icons/collab.svg b/docs/assets/images/icons/collab.svg
new file mode 100644
index 000000000000..239666a993bf
--- /dev/null
+++ b/docs/assets/images/icons/collab.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/assets/images/icons/contributing.svg b/docs/assets/images/icons/contributing.svg
new file mode 100644
index 000000000000..c814591e1c7f
--- /dev/null
+++ b/docs/assets/images/icons/contributing.svg
@@ -0,0 +1 @@
+
diff --git a/docs/assets/images/icons/faq.svg b/docs/assets/images/icons/faq.svg
new file mode 100644
index 000000000000..a3e196d298a9
--- /dev/null
+++ b/docs/assets/images/icons/faq.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/assets/images/icons/home.svg b/docs/assets/images/icons/home.svg
new file mode 100644
index 000000000000..0f7bee254cd3
--- /dev/null
+++ b/docs/assets/images/icons/home.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/assets/images/icons/requirements.svg b/docs/assets/images/icons/requirements.svg
new file mode 100644
index 000000000000..c3888f90274f
--- /dev/null
+++ b/docs/assets/images/icons/requirements.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/assets/images/icons/upgrade.svg b/docs/assets/images/icons/upgrade.svg
new file mode 100644
index 000000000000..28c35752f201
--- /dev/null
+++ b/docs/assets/images/icons/upgrade.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/assets/images/icons/usage.svg b/docs/assets/images/icons/usage.svg
new file mode 100644
index 000000000000..f38aa04813e3
--- /dev/null
+++ b/docs/assets/images/icons/usage.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/docs/assets/images/icons/wrench.svg b/docs/assets/images/icons/wrench.svg
new file mode 100644
index 000000000000..acca9b7614a1
--- /dev/null
+++ b/docs/assets/images/icons/wrench.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/assets/screenshot-1.png b/docs/assets/screenshot-1.png
new file mode 100644
index 000000000000..cacbc21bd771
Binary files /dev/null and b/docs/assets/screenshot-1.png differ
diff --git a/docs/assets/screenshot-2.png b/docs/assets/screenshot-2.png
new file mode 100644
index 000000000000..5861fac0b905
Binary files /dev/null and b/docs/assets/screenshot-2.png differ
diff --git a/docs/coder.md b/docs/coder.md
new file mode 100644
index 000000000000..eff3423b5b7a
--- /dev/null
+++ b/docs/coder.md
@@ -0,0 +1,48 @@
+# Coder
+
+To install and run code-server in a Coder workspace, we suggest using the `install.sh`
+script in your template like so:
+
+```terraform
+resource "coder_agent" "dev" {
+ arch = "amd64"
+ os = "linux"
+ startup_script = <
+
+
+# Setup Guide
+
+- [Expose code-server](#expose-code-server)
+ - [Port forwarding via SSH](#port-forwarding-via-ssh)
+ - [Using Let's Encrypt with Caddy](#using-lets-encrypt-with-caddy)
+ - [Using Let's Encrypt with NGINX](#using-lets-encrypt-with-nginx)
+ - [Using a self-signed certificate](#using-a-self-signed-certificate)
+ - [TLS 1.3 and Safari](#tls-13-and-safari)
+- [External authentication](#external-authentication)
+- [HTTPS and self-signed certificates](#https-and-self-signed-certificates)
+- [Accessing web services](#accessing-web-services)
+ - [Using a subdomain](#using-a-subdomain)
+ - [Using a subpath](#using-a-subpath)
+ - [Using your own proxy](#using-your-own-proxy)
+ - [Stripping `/proxy/` from the request path](#stripping-proxyport-from-the-request-path)
+ - [Proxying to create a React app](#proxying-to-create-a-react-app)
+ - [Proxying to a Vue app](#proxying-to-a-vue-app)
+ - [Proxying to an Angular app](#proxying-to-an-angular-app)
+ - [Proxying to a Svelte app](#proxying-to-a-svelte-app)
+ - [Prefixing `/absproxy/` with a path](#prefixing-absproxyport-with-a-path)
+ - [Preflight requests](#preflight-requests)
+- [Internationalization and customization](#internationalization-and-customization)
+ - [Available keys and placeholders](#available-keys-and-placeholders)
+ - [Legacy flag](#legacy-flag)
+
+
+
+
+This article will walk you through exposing code-server securely once you've
+completed the [installation process](install.md).
+
+## Expose code-server
+
+**Never** expose code-server directly to the internet without some form of
+authentication and encryption, otherwise someone can take over your machine via
+the terminal.
+
+By default, code-server uses password authentication. As such, you must copy the
+password from code-server's config file to log in. To avoid exposing itself
+unnecessarily, code-server listens on `localhost`; this practice is fine for
+testing, but it doesn't work if you want to access code-server from a different
+machine.
+
+> **Rate limits:** code-server rate limits password authentication attempts to
+> two per minute plus an additional twelve per hour.
+
+There are several approaches to operating and exposing code-server securely:
+
+- Port forwarding via SSH
+- Using Let's Encrypt with Caddy
+- Using Let's Encrypt with NGINX
+- Using a self-signed certificate
+
+### Port forwarding via SSH
+
+We highly recommend using [port forwarding via
+SSH](https://help.ubuntu.com/community/SSH/OpenSSH/PortForwarding) to access
+code-server. If you have an SSH server on your remote machine, this approach
+doesn't require any additional setup at all.
+
+The downside to SSH forwarding, however, is that you can't access code-server
+when using machines without SSH clients (such as iPads). If this applies to you,
+we recommend using another method, such as [Let's Encrypt](#let-encrypt) instead.
+
+> To work properly, your environment should have WebSockets enabled, which
+> code-server uses to communicate between the browser and server.
+
+1. SSH into your instance and edit the code-server config file to disable
+ password authentication:
+
+ ```console
+ # Replaces "auth: password" with "auth: none" in the code-server config.
+ sed -i.bak 's/auth: password/auth: none/' ~/.config/code-server/config.yaml
+ ```
+
+2. Restart code-server:
+
+ ```console
+ sudo systemctl restart code-server@$USER
+ ```
+
+3. Forward local port `8080` to `127.0.0.1:8080` on the remote instance by running the following command on your local machine:
+
+ ```console
+ # -N disables executing a remote shell
+ ssh -N -L 8080:127.0.0.1:8080 [user]@
+ ```
+
+4. At this point, you can access code-server by pointing your web browser to `http://127.0.0.1:8080`.
+
+5. If you'd like to make the port forwarding via SSH persistent, we recommend
+ using [mutagen](https://mutagen.io/documentation/introduction/installation)
+ to do so. Once you've installed mutagen, you can port forward as follows:
+
+ ```shell
+ # This is the same as the above SSH command, but it runs in the background
+ # continuously. Be sure to add `mutagen daemon start` to your ~/.bashrc to
+ # start the mutagen daemon when you open a shell.
+ mutagen forward create --name=code-server tcp:127.0.0.1:8080 < instance-ip > :tcp:127.0.0.1:8080
+ ```
+
+6. Optional, but highly recommended: add the following to `~/.ssh/config` so
+ that you can detect bricked SSH connections:
+
+ ```bash
+ Host *
+ ServerAliveInterval 5
+ ExitOnForwardFailure yes
+ ```
+
+> You can [forward your
+> SSH](https://developer.github.com/v3/guides/using-ssh-agent-forwarding/) and
+> [GPG agent](https://wiki.gnupg.org/AgentForwarding) to the instance to
+> securely access GitHub and sign commits without having to copy your keys.
+
+### Using Let's Encrypt with Caddy
+
+Using [Let's Encrypt](https://letsencrypt.org) is an option if you want to
+access code-server on an iPad or do not want to use SSH port forwarding.
+
+1. This option requires that the remote machine be exposed to the internet. Make sure that your instance allows HTTP/HTTPS traffic.
+
+2. You'll need a domain name (if you don't have one, you can purchase one from
+ [Google Domains](https://domains.google.com) or the domain service of your
+ choice). Once you have a domain name, add an A record to your domain that contains your
+ instance's IP address.
+
+3. Install [Caddy](https://caddyserver.com/docs/download#debian-ubuntu-raspbian):
+
+ ```console
+ sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
+ curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
+ curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
+ sudo apt update
+ sudo apt install caddy
+ ```
+
+4. Replace `/etc/caddy/Caddyfile` using `sudo` so that the file looks like this:
+
+ ```text
+ mydomain.com {
+ reverse_proxy 127.0.0.1:8080
+ }
+ ```
+
+ If you want to serve code-server from a sub-path, you can do so as follows:
+
+ ```text
+ mydomain.com/code/* {
+ uri strip_prefix /code
+ reverse_proxy 127.0.0.1:8080
+ }
+ ```
+
+ Remember to replace `mydomain.com` with your domain name!
+
+5. Reload Caddy:
+
+ ```console
+ sudo systemctl reload caddy
+ ```
+
+At this point, you should be able to access code-server via
+`https://mydomain.com`.
+
+### Using Let's Encrypt with NGINX
+
+1. This option requires that the remote machine be exposed to the internet. Make
+ sure that your instance allows HTTP/HTTPS traffic.
+
+2. You'll need a domain name (if you don't have one, you can purchase one from
+ [Google Domains](https://domains.google.com) or the domain service of your
+ choice). Once you have a domain name, add an A record to your domain that contains your
+ instance's IP address.
+
+3. Install NGINX:
+
+ ```bash
+ sudo apt update
+ sudo apt install -y nginx certbot python3-certbot-nginx
+ ```
+
+4. Update `/etc/nginx/sites-available/code-server` using sudo with the following
+ configuration:
+
+ ```text
+ server {
+ listen 80;
+ listen [::]:80;
+ server_name mydomain.com;
+
+ location / {
+ proxy_pass http://localhost:8080/;
+ proxy_set_header Host $http_host;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection upgrade;
+ proxy_set_header Accept-Encoding gzip;
+ }
+ }
+ ```
+
+ Be sure to replace `mydomain.com` with your domain name!
+
+5. Enable the config:
+ ```console
+ sudo ln -s ../sites-available/code-server /etc/nginx/sites-enabled/code-server
+ sudo certbot --non-interactive --redirect --agree-tos --nginx -d mydomain.com -m me@example.com
+ ```
+ Be sure to replace `me@example.com` with your actual email.
+
+At this point, you should be able to access code-server via
+`https://mydomain.com`.
+
+### Using a self-signed certificate
+
+> Self signed certificates do not work with iPad; see [./ipad.md](./ipad.md) for
+> more information.
+
+Before proceeding, we recommend familiarizing yourself with the [risks of
+self-signing a certificate for
+SSL](https://security.stackexchange.com/questions/8110).
+
+We recommend self-signed certificates as a last resort, since self-signed
+certificates do not work with iPads and may cause unexpected issues with
+code-server. You should only proceed with this option if:
+
+- You do not want to buy a domain or you cannot expose the remote machine to
+ the internet
+- You do not want to use port forwarding via SSH
+
+To use a self-signed certificate:
+
+1. This option requires that the remote machine be exposed to the internet. Make
+ sure that your instance allows HTTP/HTTPS traffic.
+
+1. SSH into your instance and edit your code-server config file to use a
+ randomly generated self-signed certificate:
+
+ ```console
+ # Replaces "cert: false" with "cert: true" in the code-server config.
+ sed -i.bak 's/cert: false/cert: true/' ~/.config/code-server/config.yaml
+ # Replaces "bind-addr: 127.0.0.1:8080" with "bind-addr: 0.0.0.0:443" in the code-server config.
+ sed -i.bak 's/bind-addr: 127.0.0.1:8080/bind-addr: 0.0.0.0:443/' ~/.config/code-server/config.yaml
+ # Allows code-server to listen on port 443.
+ sudo setcap cap_net_bind_service=+ep /usr/lib/code-server/lib/node
+ ```
+
+1. Restart code-server:
+
+ ```console
+ sudo systemctl restart code-server@$USER
+ ```
+
+At this point, you should be able to access code-server via
+`https://`.
+
+If you'd like to avoid the warnings displayed by code-server when using a
+self-signed certificate, you can use [mkcert](https://mkcert.dev) to create a
+self-signed certificate that's trusted by your operating system, then pass the
+certificate to code-server via the `cert` and `cert-key` config fields.
+
+### TLS 1.3 and Safari
+
+If you will be using Safari and your configuration does not allow anything less
+than TLS 1.3 you will need to add support for TLS 1.2 since Safari does not
+support TLS 1.3 for web sockets at the time of writing. If this is the case you
+should see OSSStatus: 9836 in the browser console.
+
+## External authentication
+
+If you want to use external authentication mechanism (e.g., Sign in with
+Google), you can do this with a reverse proxy such as:
+
+- [Pomerium](https://www.pomerium.com/docs/guides/code-server.html)
+- [oauth2-proxy](https://oauth2-proxy.github.io/oauth2-proxy/)
+- [Cloudflare Access](https://www.cloudflare.com/zero-trust/products/access/)
+
+## HTTPS and self-signed certificates
+
+For HTTPS, you can use a self-signed certificate by:
+
+- Passing in `--cert`
+- Passing in an existing certificate by providing the path to `--cert` and the
+ path to the key with `--cert-key`
+
+The self signed certificate will be generated to
+`~/.local/share/code-server/self-signed.crt`.
+
+If you pass a certificate to code-server, it will respond to HTTPS requests and
+redirect all HTTP requests to HTTPS.
+
+> You can use [Let's Encrypt](https://letsencrypt.org/) to get a TLS certificate
+> for free.
+
+Note: if you set `proxy_set_header Host $host;` in your reverse proxy config, it
+will change the address displayed in the green section of code-server in the
+bottom left to show the correct address.
+
+## Accessing web services
+
+If you're working on web services and want to access them locally, code-server
+can proxy to any port using either a subdomain or a subpath, allowing you to
+securely access these services using code-server's built-in authentication.
+
+### Using a subdomain
+
+You will need a DNS entry that points to your server for each port you want to
+access. You can either set up a wildcard DNS entry for `*.` if your
+domain name registrar supports it, or you can create one for every port you want
+to access (`3000.`, `8080.`, etc).
+
+You should also set up TLS certificates for these subdomains, either using a
+wildcard certificate for `*.` or individual certificates for each port.
+
+To set your domain, start code-server with the `--proxy-domain` flag:
+
+```console
+code-server --proxy-domain
+```
+
+For instance, if you have code-server exposed on `domain.tld` and a Python
+server running on port 8080 of the same machine code-server is running on, you
+could run code-server with `--proxy-domain domain.tld` and access the Python
+server via `8080.domain.tld`.
+
+Note that this uses the host header, so ensure your reverse proxy (if you're
+using one) forwards that information.
+
+### Using a subpath
+
+Simply browse to `/proxy//`. For instance, if you have code-server
+exposed on `domain.tld` and a Python server running on port 8080 of the same
+machine code-server is running on, you could access the Python server via
+`domain.tld/proxy/8000`.
+
+### Using your own proxy
+
+You can make extensions and the ports panel use your own proxy by setting
+`VSCODE_PROXY_URI`. For example if you set
+`VSCODE_PROXY_URI=https://{{port}}.kyle.dev` when an application is detected
+running on port 3000 of the same machine code-server is running on the ports
+panel will create a link to https://3000.kyle.dev instead of pointing to the
+built-in subpath-based proxy.
+
+Note: relative paths are also supported i.e.
+`VSCODE_PROXY_URI=./proxy/{{port}}`
+
+### Stripping `/proxy/` from the request path
+
+You may notice that the code-server proxy strips `/proxy/` from the
+request path.
+
+HTTP servers should use relative URLs to avoid the need to be coupled to the
+absolute path at which they are served. This means you must [use trailing
+slashes on all paths with
+subpaths](https://blog.cdivilly.com/2019/02/28/uri-trailing-slashes).
+
+This reasoning is why the default behavior is to strip `/proxy/` from the
+base path. If your application uses relative URLs and does not assume the
+absolute path at which it is being served, it will just work no matter what port
+you decide to serve it off or if you put it in behind code-server or any other
+proxy.
+
+However, some prefer the cleaner aesthetic of no trailing slashes. Omitting the
+trailing slashes couples you to the base path, since you cannot use relative
+redirects correctly anymore. If you're okay with this tradeoff, use `/absproxy`
+instead and the path will be passed as is (e.g., `/absproxy/3000/my-app-path`).
+
+### Proxying to create a React app
+
+You must use `/absproxy/` with `create-react-app` (see
+[#2565](https://github.com/coder/code-server/issues/2565) and
+[#2222](https://github.com/coder/code-server/issues/2222) for more information).
+You will need to inform `create-react-app` of the path at which you are serving
+via `$PUBLIC_URL` and webpack via `$WDS_SOCKET_PATH`:
+
+```sh
+PUBLIC_URL=/absproxy/3000 \
+ WDS_SOCKET_PATH=$PUBLIC_URL/sockjs-node \
+ BROWSER=none yarn start
+```
+
+You should then be able to visit
+`https://my-code-server-address.io/absproxy/3000` to see your app exposed
+through code-server.
+
+> We highly recommend using the subdomain approach instead to avoid this class of issue.
+
+### Proxying to a Vue app
+
+Similar to the situation with React apps, you have to make a few modifications
+to proxy a Vue app.
+
+1. add `vue.config.js`
+2. update the values to match this (you can use any free port):
+
+```js
+module.exports = {
+ devServer: {
+ port: 3454,
+ sockPath: "sockjs-node",
+ },
+ publicPath: "/absproxy/3454",
+}
+```
+
+3. access app at `