diff --git a/.dockerignore b/.dockerignore
index cbfebc09e59c..9bcce7a80897 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,12 +1,3 @@
-Dockerfile
-build
-deployment
-doc
-.github
-.gitignore
-.node-version
-.travis.yml
-LICENSE
-README.md
-node_modules
-release
\ No newline at end of file
+**
+!release-packages
+!ci
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 000000000000..65705d954568
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,6 @@
+root = true
+
+[*]
+indent_style = space
+trim_trailing_whitespace = true
+indent_size = 2
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
new file mode 100644
index 000000000000..793a923d16eb
--- /dev/null
+++ b/.git-blame-ignore-revs
@@ -0,0 +1,2 @@
+# Prettier 3.4.2
+9b0340a09276f93c054d705d1b9a5f24cc5dbc97
\ No newline at end of file
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000000..dc5caf936908
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+*.afdesign filter=lfs diff=lfs merge=lfs -text
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 11fee14e7271..04718d97bc09 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -1,2 +1,7 @@
-* @code-asher @kylecarbs
-Dockerfile @nhooyr
+* @coder/code-server
+
+ci/helm-chart/ @Matthew-Beckett @alexgorbatchev
+
+docs/install.md @GNUxeava
+
+src/node/i18n/locales/zh-cn.json @zhaozhiming
diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml
new file mode 100644
index 000000000000..c43d5c65e23b
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug-report.yml
@@ -0,0 +1,126 @@
+name: Bug report
+description: File a bug report
+labels: ["bug", "triage"]
+body:
+ - type: checkboxes
+ attributes:
+ label: Is there an existing issue for this?
+ description: Please search to see if an issue already exists for the bug you encountered.
+ options:
+ - label: I have searched the existing issues
+ required: true
+
+ - type: textarea
+ attributes:
+ label: OS/Web Information
+ description: |
+ examples:
+ - **Web Browser**: Chrome
+ - **Local OS**: macOS
+ - **Remote OS**: Ubuntu
+ - **Remote Architecture**: amd64
+ - **`code-server --version`**: 4.0.1
+
+ Please do not just put "latest" for the version.
+ value: |
+ - Web Browser:
+ - Local OS:
+ - Remote OS:
+ - Remote Architecture:
+ - `code-server --version`:
+ validations:
+ required: true
+
+ - type: textarea
+ attributes:
+ label: Steps to Reproduce
+ description: |
+ Please describe exactly how to reproduce the bug. For example:
+ 1. Open code-server in Firefox
+ 2. Install extension `foo.bar` from the extensions sidebar
+ 3. Run command `foo.bar.baz`
+ value: |
+ 1.
+ 2.
+ 3.
+ validations:
+ required: true
+
+ - type: textarea
+ attributes:
+ label: Expected
+ description: What should happen?
+ validations:
+ required: true
+
+ - type: textarea
+ attributes:
+ label: Actual
+ description: What actually happens?
+ validations:
+ required: true
+
+ - type: textarea
+ id: logs
+ attributes:
+ label: Logs
+ description: Run code-server with the --verbose flag and then paste any relevant logs from the server, from the browser console and/or the browser network tab. For issues with installation, include installation logs (i.e. output of `npm install -g code-server`).
+ render: shell
+
+ - type: textarea
+ attributes:
+ label: Screenshot/Video
+ description: Please include a screenshot, gif or screen recording of your issue.
+ validations:
+ required: false
+
+ - type: dropdown
+ attributes:
+ label: Does this bug reproduce in native VS Code?
+ description: If the bug reproduces in native VS Code, submit the issue upstream instead (https://github.com/microsoft/vscode).
+ options:
+ - Yes, this is also broken in native VS Code
+ - No, this works as expected in native VS Code
+ - This cannot be tested in native VS Code
+ - I did not test native VS Code
+ validations:
+ required: true
+
+ - type: dropdown
+ attributes:
+ label: Does this bug reproduce in VS Code web?
+ description: If the bug reproduces in VS Code web, submit the issue upstream instead (https://github.com/microsoft/vscode). You can run VS Code web with `code serve-web` (this is not the same as vscode.dev).
+ options:
+ - Yes, this is also broken in VS Code web
+ - No, this works as expected in VS Code web
+ - This cannot be tested in VS Code web
+ - I did not test VS Code web
+ validations:
+ required: true
+
+ - type: dropdown
+ attributes:
+ label: Does this bug reproduce in GitHub Codespaces?
+ description: If the bug reproduces in GitHub Codespaces, submit the issue upstream instead (https://github.com/microsoft/vscode).
+ options:
+ - Yes, this is also broken in GitHub Codespaces
+ - No, this works as expected in GitHub Codespaces
+ - This cannot be tested in GitHub Codespaces
+ - I did not test GitHub Codespaces
+ validations:
+ required: true
+
+ - type: checkboxes
+ attributes:
+ label: Are you accessing code-server over a secure context?
+ description: code-server relies on service workers (which only work in secure contexts) for many features. Double-check that you are using a secure context like HTTPS or localhost.
+ options:
+ - label: I am using a secure context.
+ required: false
+
+ - type: textarea
+ attributes:
+ label: Notes
+ description: Please include any addition notes that will help us resolve this issue.
+ validations:
+ required: false
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index 50e90f1f21fa..000000000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,22 +0,0 @@
----
-name: Bug Report
-about: Report problems and unexpected behavior.
-title: ''
-labels: 'bug'
-assignees: ''
----
-
-
-
-
-- `code-server` version:
-- OS Version:
-
-## Description
-
-
-
-## Steps to Reproduce
-
-1.
-1.
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 000000000000..e24498346339
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,8 @@
+blank_issues_enabled: false
+contact_links:
+ - name: Question?
+ url: https://github.com/coder/code-server/discussions/new?category_id=22503114
+ about: Ask the community for help on our GitHub Discussions board
+ - name: code-server Slack Community
+ about: Need immediate help or just want to talk? Hop in our Slack. Note - this Slack is not actively monitored by code-server maintainers.
+ url: https://cdr.co/join-community
diff --git a/.github/ISSUE_TEMPLATE/doc.md b/.github/ISSUE_TEMPLATE/doc.md
new file mode 100644
index 000000000000..75240e7f7631
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/doc.md
@@ -0,0 +1,11 @@
+---
+name: Documentation improvement
+about: Suggest a documentation improvement
+labels: "docs"
+---
+
+## What is your suggestion?
+
+## How will this improve the docs?
+
+## Are you interested in submitting a PR for this?
diff --git a/.github/ISSUE_TEMPLATE/extension_bug.md b/.github/ISSUE_TEMPLATE/extension_bug.md
deleted file mode 100644
index 7c30b9479417..000000000000
--- a/.github/ISSUE_TEMPLATE/extension_bug.md
+++ /dev/null
@@ -1,22 +0,0 @@
----
-name: Extension Bug
-about: Report problems and unexpected behavior with extensions.
-title: ''
-labels: 'extension-specific'
-assignees: ''
----
-
-
-
-- `code-server` version:
-- OS Version:
-- Extension:
-
-## Description
-
-
-
-## Steps to Reproduce
-
-1.
-1.
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md
new file mode 100644
index 000000000000..89837e3441e6
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature-request.md
@@ -0,0 +1,13 @@
+---
+name: Feature request
+about: Suggest an idea to improve code-server
+labels: enhancement
+---
+
+## What is your suggestion?
+
+## Why do you want this feature?
+
+## Are there any workarounds to get this functionality today?
+
+## Are you interested in submitting a PR for this?
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
deleted file mode 100644
index b33f67bc7ebf..000000000000
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-name: Feature Request
-about: Suggest an idea for this project.
-title: ''
-labels: 'feature'
-assignees: ''
----
-
-
-
-
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md
deleted file mode 100644
index 3c234cd1c76c..000000000000
--- a/.github/ISSUE_TEMPLATE/question.md
+++ /dev/null
@@ -1,17 +0,0 @@
----
-name: Question
-about: Ask a question.
-title: ''
-labels: 'question'
-assignees: ''
----
-
-
-
-## Description
-
-
-
-## Related Issues
-
-
\ No newline at end of file
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 000000000000..e240a5f49c8d
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,8 @@
+
+
+Fixes #
diff --git a/.github/codecov.yml b/.github/codecov.yml
new file mode 100644
index 000000000000..c2e23821411d
--- /dev/null
+++ b/.github/codecov.yml
@@ -0,0 +1,31 @@
+codecov:
+ require_ci_to_pass: yes
+ allow_coverage_offsets: True
+
+coverage:
+ precision: 2
+ round: down
+ range: "40...70"
+ status:
+ patch: off
+ notify:
+ slack:
+ default:
+ url: secret:v1::tXC7VwEIKYjNU8HRgRv2GdKOSCt5UzpykKZb+o1eCDqBgb2PEqwE3A26QUPYMLo4BO2qtrJhFIvwhUvlPwyzDCNGoNiuZfXr0UeZZ0y1TcZu672R/NBNMwEPO/e1Ye0pHxjzKHnuH7HqbjFucox/RBQLtiL3J56SWGE3JtbkC6o=
+ threshold: 1%
+ only_pulls: false
+ branches:
+ - "main"
+
+parsers:
+ gcov:
+ branch_detection:
+ conditional: yes
+ loop: yes
+ method: no
+ macro: no
+
+comment:
+ layout: "reach,diff,flags,files,footer"
+ behavior: default
+ require_changes: no
diff --git a/.github/codeql-config.yml b/.github/codeql-config.yml
new file mode 100644
index 000000000000..9f98cc2a62b1
--- /dev/null
+++ b/.github/codeql-config.yml
@@ -0,0 +1 @@
+name: "code-server CodeQL config"
diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml
new file mode 100644
index 000000000000..d39541471001
--- /dev/null
+++ b/.github/dependabot.yaml
@@ -0,0 +1,31 @@
+version: 2
+updates:
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "monthly"
+ time: "06:00"
+ timezone: "America/Chicago"
+ cooldown:
+ default-days: 7
+ labels: []
+
+ - package-ecosystem: "npm"
+ directory: "/"
+ schedule:
+ interval: "monthly"
+ time: "06:00"
+ timezone: "America/Chicago"
+ cooldown:
+ default-days: 7
+ labels: []
+ ignore:
+ # Ignore patch updates for all dependencies
+ - dependency-name: "*"
+ update-types:
+ - version-update:semver-patch
+ # Ignore major updates to Node.js types, because they need to
+ # correspond to the Node.js engine version
+ - dependency-name: "@types/node"
+ update-types:
+ - version-update:semver-major
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
deleted file mode 100644
index e056fdf5f161..000000000000
--- a/.github/pull_request_template.md
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-### Describe in detail the problem you had and how this PR fixes it
-
-### Is there an open issue you can link to?
-
diff --git a/.github/stale.yml b/.github/stale.yml
new file mode 100644
index 000000000000..945de5a3e12a
--- /dev/null
+++ b/.github/stale.yml
@@ -0,0 +1,12 @@
+# Number of days of inactivity before an issue becomes stale
+daysUntilStale: 180
+# Number of days of inactivity before a stale issue is closed
+daysUntilClose: 5
+# Label to apply when stale.
+staleLabel: stale
+# Comment to post when marking an issue as stale. Set to `false` to disable
+markComment: >
+ This issue has been automatically marked as stale because it has not had
+ recent activity. It will be closed if no activity occurs in the next 5 days.
+# Comment to post when closing a stale issue. Set to `false` to disable
+closeComment: false
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
new file mode 100644
index 000000000000..22d27335ab8e
--- /dev/null
+++ b/.github/workflows/build.yaml
@@ -0,0 +1,311 @@
+name: Build
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+ branches:
+ - main
+
+# Cancel in-progress runs for pull requests when developers push
+# additional changes, and serialize builds in branches.
+# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-concurrency-to-cancel-any-in-progress-job-or-run
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
+
+jobs:
+ changes:
+ runs-on: ubuntu-latest
+ outputs:
+ ci: ${{ steps.filter.outputs.ci }}
+ code: ${{ steps.filter.outputs.code }}
+ npm: ${{ steps.filter.outputs.npm }}
+ vscode: ${{ steps.filter.outputs.vscode }}
+ docs: ${{ steps.filter.outputs.docs }}
+ helm: ${{ steps.filter.outputs.helm }}
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+ - uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3
+ id: filter
+ with:
+ filters: |
+ ci:
+ - ".github/**"
+ - "ci/**"
+ docs:
+ - "docs/**"
+ - "README.md"
+ - "CHANGELOG.md"
+ helm:
+ - "ci/helm-chart/**"
+ code:
+ - "src/**"
+ - "test/**"
+ npm:
+ - "package-lock.json"
+ - "test/package-lock.json"
+ vscode:
+ - "lib/**"
+ - "patches/**"
+ - id: debug
+ run: |
+ echo "${{ toJSON(steps.filter )}}"
+
+ prettier:
+ name: Run prettier check
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
+ with:
+ node-version-file: .node-version
+ cache: npm
+ cache-dependency-path: |
+ package-lock.json
+ test/package-lock.json
+ - run: SKIP_SUBMODULE_DEPS=1 npm ci
+ - run: npx prettier --check .
+
+ doctoc:
+ name: Doctoc markdown files
+ runs-on: ubuntu-22.04
+ needs: changes
+ if: needs.changes.outputs.docs == 'true'
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
+ with:
+ node-version-file: .node-version
+ cache: npm
+ cache-dependency-path: |
+ package-lock.json
+ test/package-lock.json
+ - run: SKIP_SUBMODULE_DEPS=1 npm ci
+ - run: npm run doctoc
+
+ lint-helm:
+ name: Lint Helm chart
+ runs-on: ubuntu-22.04
+ needs: changes
+ if: needs.changes.outputs.helm == 'true'
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+ - uses: bmuschko/setup-kubeconform@e5d264ec1eafe2314e750c429a9da7639dd5a003 # v1.1.0
+ with:
+ kubeconform-version: "0.8.0"
+ - run: kubeconform ci/helm-chart
+
+ lint-ts:
+ name: Lint TypeScript files
+ runs-on: ubuntu-22.04
+ needs: changes
+ if: needs.changes.outputs.code == 'true' || needs.changes.outputs.ci == 'true' || needs.changes.outputs.npm == 'true'
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
+ with:
+ node-version-file: .node-version
+ cache: npm
+ cache-dependency-path: |
+ package-lock.json
+ test/package-lock.json
+ - run: SKIP_SUBMODULE_DEPS=1 npm ci
+ - run: npm run lint:ts
+
+ lint-actions:
+ name: Lint GitHub Actions
+ runs-on: ubuntu-latest
+ needs: changes
+ if: needs.changes.outputs.ci == 'true'
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+ - name: Check workflow files
+ run: |
+ bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) 1.7.9
+ ./actionlint -color -shellcheck= -ignore "softprops/action-gh-release"
+ shell: bash
+
+ test-unit:
+ name: Run unit tests
+ runs-on: ubuntu-22.04
+ needs: changes
+ if: needs.changes.outputs.code == 'true' || needs.changes.outputs.npm == 'true'
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
+ with:
+ node-version-file: .node-version
+ cache: npm
+ cache-dependency-path: |
+ package-lock.json
+ test/package-lock.json
+ - run: SKIP_SUBMODULE_DEPS=1 npm ci
+ - run: npm run test:unit
+ - uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
+ if: success()
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+
+ build:
+ name: linux-x64
+ runs-on: ubuntu-22.04
+ env:
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
+ DISABLE_V8_COMPILE_CACHE: 1
+ VERSION: 0.0.0
+ VSCODE_ARCH: x64
+ VSCODE_TARGET: linux-x64
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ ELECTRON_SKIP_BINARY_DOWNLOAD: 1
+ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
+
+ steps:
+ - run: sudo apt update && sudo apt install -y libkrb5-dev
+ - uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # latest
+ with:
+ packages: quilt
+ version: 1.0
+
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+ with:
+ submodules: true
+ - run: quilt push -a
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
+ with:
+ node-version-file: .node-version
+ cache: npm
+ cache-dependency-path: |
+ package-lock.json
+ test/package-lock.json
+
+ # Get Code's git hash. When this changes it means the content is
+ # different and we need to rebuild.
+ - name: Get latest lib/vscode rev
+ id: vscode-rev
+ run: echo "rev=$(git rev-parse HEAD:./lib/vscode)" >> $GITHUB_OUTPUT
+
+ # We need to rebuild when we have a new version of Code, when any of the
+ # patches changed, or when the code-server version changes (since it gets
+ # embedded into the code). Use VSCODE_CACHE_VERSION to force a rebuild.
+ - name: Fetch prebuilt linux-x64 Code package from cache
+ id: cache-vscode
+ uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
+ with:
+ path: lib/vscode-reh-web-linux-x64
+ key: vscode-linux-x64-package-${{ secrets.VSCODE_CACHE_VERSION }}-${{ steps.vscode-rev.outputs.rev }}-${{ hashFiles('patches/*.diff', 'ci/build/build-vscode.sh') }}
+ - name: Build vscode
+ if: steps.cache-vscode.outputs.cache-hit != 'true'
+ run: |
+ cd lib/vscode/build
+ npm ci
+ cd ..
+ source ./build/azure-pipelines/linux/setup-env.sh
+ # Run preinstall script before root dependencies are installed
+ # so that v8 headers are patched correctly for native modules.
+ node build/npm/preinstall.ts
+ npm ci
+ cd ../..
+ npm run build:vscode
+
+ # Build the code-server wrapper.
+ - run: SKIP_SUBMODULE_DEPS=1 npm ci
+ - run: npm run build
+
+ # Push up an artifact containing the linux-x64 release.
+ - run: KEEP_MODULES=1 npm run release
+ - run: tar -czf package.tar.gz release
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
+ with:
+ name: linux-x64-package
+ path: ./package.tar.gz
+
+ test-e2e:
+ name: Run e2e tests
+ runs-on: ubuntu-22.04
+ env:
+ LOG_LEVEL: debug
+ needs: [changes, build]
+ if: needs.changes.outputs.code == 'true' || needs.changes.outputs.npm == 'true' || needs.changes.outputs.vscode == 'true' || needs.changes.outputs.ci == 'true'
+
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
+ with:
+ node-version-file: .node-version
+ cache: npm
+ cache-dependency-path: |
+ package-lock.json
+ test/package-lock.json
+ - run: SKIP_SUBMODULE_DEPS=1 npm ci
+ - name: Install Playwright OS dependencies
+ run: |
+ ./test/node_modules/.bin/playwright install-deps
+ ./test/node_modules/.bin/playwright install
+
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
+ with:
+ name: linux-x64-package
+ - run: tar -xzf package.tar.gz
+
+ - run: CODE_SERVER_TEST_ENTRY=./release npm run test:e2e
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
+ if: always()
+ with:
+ name: failed-test-videos
+ path: ./test/test-results
+
+ test-e2e-proxy:
+ name: Run e2e tests behind proxy
+ runs-on: ubuntu-22.04
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ LOG_LEVEL: debug
+ needs: [changes, build]
+ if: needs.changes.outputs.code == 'true' || needs.changes.outputs.npm == 'true' || needs.changes.outputs.vscode == 'true' || needs.changes.outputs.ci == 'true'
+
+ steps:
+ - name: Cache Caddy
+ uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
+ id: caddy-cache
+ with:
+ path: |
+ ~/.cache/caddy
+ key: cache-caddy-2.5.2
+ - name: Install Caddy
+ if: steps.caddy-cache.outputs.cache-hit != 'true'
+ run: |
+ gh release download v2.5.2 --repo caddyserver/caddy --pattern "caddy_2.5.2_linux_amd64.tar.gz"
+ mkdir -p ~/.cache/caddy
+ tar -xzf caddy_2.5.2_linux_amd64.tar.gz --directory ~/.cache/caddy
+
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
+ with:
+ node-version-file: .node-version
+ cache: npm
+ cache-dependency-path: |
+ package-lock.json
+ test/package-lock.json
+ - run: SKIP_SUBMODULE_DEPS=1 npm ci
+ - name: Install Playwright OS dependencies
+ run: |
+ ./test/node_modules/.bin/playwright install-deps
+ ./test/node_modules/.bin/playwright install
+
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
+ with:
+ name: linux-x64-package
+ - run: tar -xzf package.tar.gz
+
+ - run: ~/.cache/caddy/caddy start --config ./ci/Caddyfile
+ - run: CODE_SERVER_TEST_ENTRY=./release npm run test:e2e:proxy
+ - run: ~/.cache/caddy/caddy stop --config ./ci/Caddyfile
+ if: always()
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
+ if: always()
+ with:
+ name: failed-test-videos-proxy
+ path: ./test/test-results
diff --git a/.github/workflows/installer.yaml b/.github/workflows/installer.yaml
new file mode 100644
index 000000000000..1777844dd11b
--- /dev/null
+++ b/.github/workflows/installer.yaml
@@ -0,0 +1,76 @@
+name: Installer integration
+
+on:
+ push:
+ branches:
+ - main
+ paths:
+ - "install.sh"
+ - ".github/workflows/installer.yaml"
+ pull_request:
+ branches:
+ - main
+ paths:
+ - "install.sh"
+ - ".github/workflows/installer.yaml"
+
+# Cancel in-progress runs for pull requests when developers push
+# additional changes, and serialize builds in branches.
+# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-concurrency-to-cancel-any-in-progress-job-or-run
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
+
+permissions:
+ contents: read
+
+jobs:
+ ubuntu:
+ name: Test installer on Ubuntu
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+
+ - name: Install code-server
+ run: ./install.sh
+
+ - name: Test code-server was installed globally
+ run: code-server --help
+
+ alpine:
+ name: Test installer on Alpine
+ runs-on: ubuntu-latest
+ container: "alpine:3.17"
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+
+ - name: Install curl
+ run: apk add curl
+
+ - name: Add user
+ run: adduser coder --disabled-password
+
+ # Standalone should work without root.
+ - name: Test standalone to a non-existent prefix
+ run: su coder -c "./install.sh --method standalone --prefix /tmp/does/not/yet/exist"
+
+ # We do not actually have Alpine standalone builds so running code-server
+ # will not work.
+ - name: Test code-server was installed to prefix
+ run: test -f /tmp/does/not/yet/exist/bin/code-server
+
+ macos:
+ name: Test installer on macOS
+ runs-on: macos-latest
+
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+
+ - name: Install code-server
+ run: ./install.sh
+
+ - name: Test code-server was installed globally
+ run: code-server --help
diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml
new file mode 100644
index 000000000000..32cf8370e817
--- /dev/null
+++ b/.github/workflows/publish.yaml
@@ -0,0 +1,167 @@
+name: Publish code-server
+
+on:
+ # Shows the manual trigger in GitHub UI
+ # helpful as a back-up in case the GitHub Actions Workflow fails
+ workflow_dispatch:
+ inputs:
+ version:
+ type: string
+ required: true
+
+ release:
+ types: [released]
+
+# Cancel in-progress runs for pull requests when developers push
+# additional changes, and serialize builds in branches.
+# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-concurrency-to-cancel-any-in-progress-job-or-run
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
+
+jobs:
+ npm:
+ runs-on: ubuntu-latest
+ env:
+ TAG: ${{ inputs.version || github.ref_name }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
+ NPM_ENVIRONMENT: "production"
+
+ steps:
+ - name: Set version to tag without leading v
+ run: |
+ echo "VERSION=${TAG#v}" >> $GITHUB_ENV
+
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
+ with:
+ node-version-file: .node-version
+
+ - uses: robinraju/release-downloader@28fc21f50d76778e7023361aa1f863e717d3d56f # v1.13
+ with:
+ repository: "coder/code-server"
+ tag: ${{ env.TAG }}
+ fileName: "package.tar.gz"
+ out-file-path: "release-npm-package"
+
+ - run: tar -xzf release-npm-package/package.tar.gz
+ - run: |
+ echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
+ pushd release
+ npm publish --tag latest --access public
+
+ aur:
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+ env:
+ GH_TOKEN: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
+ TAG: ${{ inputs.version || github.ref_name }}
+
+ steps:
+ - name: Set version to tag without leading v
+ run: |
+ echo "VERSION=${TAG#v}" >> $GITHUB_ENV
+
+ - name: Checkout code-server-aur repo
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+ with:
+ repository: "cdrci/code-server-aur"
+ token: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
+ ref: "master"
+
+ - name: Configure git
+ run: |
+ git config --global user.name cdrci
+ git config --global user.email opensource@coder.com
+
+ - name: Fetch and reset master
+ run: |
+ git remote add upstream https://github.com/coder/code-server-aur.git
+ git fetch upstream
+ git reset --hard upstream/master
+ git push --force
+
+ - name: Validate package
+ uses: heyhusen/archlinux-package-action@3f7aaada28c782497bfe02d6d6ea365b25fdea12 # v3.0.1
+ with:
+ pkgver: ${{ env.VERSION }}
+ updpkgsums: true
+ srcinfo: true
+
+ - name: Open PR
+ run: |
+ git checkout -b update-version-${{ env.VERSION }}
+ git add .
+ git commit -m "Update to ${{ env.VERSION }}"
+ git push -u origin $(git branch --show)
+ gh pr create --repo coder/code-server-aur --title "Update to ${{ env.VERSION }}" --body "PR opened by @$GITHUB_ACTOR" --assignee $GITHUB_ACTOR
+
+ docker:
+ runs-on: ubuntu-latest
+ env:
+ GITHUB_TOKEN: ${{ github.token }}
+ TAG: ${{ inputs.version || github.ref_name }}
+
+ steps:
+ - name: Set version to tag without leading v
+ run: |
+ echo "VERSION=${TAG#v}" >> $GITHUB_ENV
+
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+ - uses: docker/setup-qemu-action@1f40c72289eff860ee54a304f1438e3cff362e0a # v4.3.0
+ - uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
+
+ - uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
+ with:
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_PASSWORD }}
+ - uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - uses: robinraju/release-downloader@28fc21f50d76778e7023361aa1f863e717d3d56f # v1.13
+ with:
+ repository: "coder/code-server"
+ tag: v${{ env.VERSION }}
+ fileName: "*.deb"
+ out-file-path: "release-packages"
+ - uses: robinraju/release-downloader@28fc21f50d76778e7023361aa1f863e717d3d56f # v1.13
+ with:
+ repository: "coder/code-server"
+ tag: v${{ env.VERSION }}
+ fileName: "*.rpm"
+ out-file-path: "release-packages"
+
+ - run: npm run publish:docker
+
+ repo:
+ runs-on: ubuntu-latest
+ env:
+ GH_TOKEN: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
+ TAG: ${{ inputs.version || github.ref_name }}
+ needs: docker
+
+ steps:
+ - name: Set version to tag without leading v
+ run: |
+ echo "VERSION=${TAG#v}" >> $GITHUB_ENV
+
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+
+ - run: ./ci/build/update-repo.sh
+
+ - name: Open PR
+ run: |
+ git config --global user.name cdrci
+ git config --global user.email opensource@coder.com
+ git checkout -b "helm/$VERSION"
+ git add .
+ git commit -m "Update Helm chart and changelog with $VERSION"
+ git push -u origin "$(git branch --show)"
+ gh pr create \
+ --repo coder/code-server \
+ --body-file .cache/checklist \
+ --title "Update Helm chart and changelog with $VERSION"
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
new file mode 100644
index 000000000000..7d24603a9ae6
--- /dev/null
+++ b/.github/workflows/release.yaml
@@ -0,0 +1,356 @@
+name: Draft release
+
+on:
+ workflow_dispatch:
+ inputs:
+ version:
+ type: string
+ required: true
+ pull_request_target:
+ types:
+ - closed
+ branches:
+ - main
+
+permissions:
+ contents: write # For creating releases.
+ discussions: write # For creating a discussion.
+
+# Cancel in-progress runs for pull requests when developers push
+# additional changes
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
+
+jobs:
+ package-linux:
+ name: ${{ format('linux-{0}', matrix.vscode_arch) }}
+ runs-on: ubuntu-22.04
+ if: >-
+ (github.event_name == 'workflow_dispatch') ||
+ (github.event_name == 'pull_request_target' && github.event.pull_request.merged == true && startsWith(github.head_ref, 'update/'))
+
+ strategy:
+ matrix:
+ include:
+ - npm_arch: x64
+ vscode_arch: x64
+ package_arch: amd64
+ - npm_arch: arm64
+ vscode_arch: arm64
+ package_arch: arm64
+
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ ELECTRON_SKIP_BINARY_DOWNLOAD: 1
+ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
+ TAG: ${{ inputs.version || github.event.pull_request.head.ref || github.ref_name }}
+ # Set release package name.
+ ARCH: ${{ matrix.package_arch }}
+ # Cross-compile target.
+ VSCODE_ARCH: ${{ matrix.vscode_arch }}
+ npm_config_arch: ${{ matrix.npm_arch }}
+ # Ensure native modules are built from source to avoid prebuilds and use
+ # the correct version of glibc.
+ npm_config_build_from_source: true
+ # Gulp target name.
+ # TODO: Pull from VSCODE_ARCH instead.
+ VSCODE_TARGET: ${{ format('linux-{0}', matrix.vscode_arch) }}
+
+ steps:
+ - run: sudo apt update && sudo apt install -y libkrb5-dev
+ - uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # latest
+ with:
+ packages: quilt
+ version: 1.0
+ - name: Install nfpm
+ run: |
+ mkdir -p ~/.local/bin
+ curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
+ echo "$HOME/.local/bin" >> $GITHUB_PATH
+
+ - name: Strip update/ and v from tag and set major version
+ run: |
+ version=${TAG#update/}
+ version=${version#v}
+ version=4${version:1}
+ echo "VERSION=$version" >> $GITHUB_ENV
+
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+ with:
+ submodules: true
+ # When an update/ branch is merged, a release is automatically created
+ # which requires secrets.
+ allow-unsafe-pr-checkout: true
+ - run: quilt push -a
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
+ with:
+ node-version-file: .node-version
+ cache: npm
+ cache-dependency-path: |
+ package-lock.json
+ test/package-lock.json
+
+ - name: Build
+ run: |
+ cd lib/vscode/build
+ npm ci
+ cd ..
+ source ./build/azure-pipelines/linux/setup-env.sh
+ # Run preinstall script before root dependencies are installed
+ # so that v8 headers are patched correctly for native modules.
+ node build/npm/preinstall.ts
+ cd ../..
+ npm ci
+ npm run build
+ npm run build:vscode
+
+ # Platform-agnostic NPM package.
+ - run: npm run release
+ if: ${{ matrix.vscode_arch == 'x64' }}
+ - run: tar -czf package.tar.gz release
+ if: ${{ matrix.vscode_arch == 'x64' }}
+ - run: |
+ sed "/^## Unreleased/,/^## / ! d" CHANGELOG.md | head -n -2 | tail -n +3 > .cache/release-notes
+ if: ${{ matrix.vscode_arch == 'x64' }}
+ - uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
+ if: ${{ matrix.vscode_arch == 'x64' }}
+ with:
+ draft: true
+ discussion_category_name: "📣 Announcements"
+ files: package.tar.gz
+ tag_name: v${{ env.VERSION }}
+ name: v${{ env.VERSION }}
+ body_path: .cache/release-notes
+
+ # Platform-specific release.
+ - run: KEEP_MODULES=1 npm run release
+ - run: npm run package
+ - uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
+ with:
+ draft: true
+ discussion_category_name: "📣 Announcements"
+ files: ./release-packages/*
+ tag_name: v${{ env.VERSION }}
+ name: v${{ env.VERSION }}
+
+ package-macos:
+ name: ${{ matrix.vscode_target }}
+ runs-on: ${{ matrix.os }}
+ if: >-
+ (github.event_name == 'workflow_dispatch') ||
+ (github.event_name == 'pull_request_target' && github.event.pull_request.merged == true && startsWith(github.head_ref, 'update/'))
+ strategy:
+ matrix:
+ include:
+ - os: macos-15-intel
+ vscode_target: darwin-x64
+ - os: macos-latest
+ vscode_target: darwin-arm64
+ env:
+ VSCODE_TARGET: ${{ matrix.vscode_target }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ TAG: ${{ inputs.version || github.event.pull_request.head.ref || github.ref_name }}
+ # Ensure native modules are built from source to avoid prebuilds.
+ npm_config_build_from_source: true
+
+ steps:
+ # The version of node-gyp we use depends on distutils but it was removed
+ # in Python 3.12. It seems to be fixed in the latest node-gyp so when we
+ # next update Node we can probably remove this. For now, install
+ # setuptools since it contains distutils.
+ - run: brew install python-setuptools quilt
+ - name: Install nfpm
+ run: |
+ mkdir -p ~/.local/bin
+ curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
+ echo "$HOME/.local/bin" >> $GITHUB_PATH
+
+ - name: Strip update/ and v from tag and set major version
+ run: |
+ version=${TAG#update/}
+ version=${version#v}
+ version=4${version:1}
+ echo "VERSION=$version" >> $GITHUB_ENV
+
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+ with:
+ submodules: true
+ # When an update/ branch is merged, a release is automatically created
+ # which requires secrets.
+ allow-unsafe-pr-checkout: true
+ - run: quilt push -a
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
+ with:
+ node-version-file: .node-version
+ cache: npm
+ cache-dependency-path: |
+ package-lock.json
+ test/package-lock.json
+
+ - run: npm ci
+ - run: npm run build
+ - run: npm run build:vscode
+ - run: KEEP_MODULES=1 npm run release
+ - run: npm run test:native
+
+ - run: npm run package
+ - uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
+ with:
+ draft: true
+ discussion_category_name: "📣 Announcements"
+ files: ./release-packages/*
+ tag_name: v${{ env.VERSION }}
+ name: v${{ env.VERSION }}
+
+ package-windows:
+ name: win32-x64
+ runs-on: windows-2022
+ if: >-
+ (github.event_name == 'workflow_dispatch') ||
+ (github.event_name == 'pull_request_target' && github.event.pull_request.merged == true && startsWith(github.head_ref, 'update/'))
+
+ defaults:
+ run:
+ shell: bash
+
+ env:
+ VSCODE_TARGET: win32-x64
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ TAG: ${{ inputs.version || github.event.pull_request.head.ref || github.ref_name }}
+ # Ensure native modules are built from source to avoid prebuilds.
+ npm_config_build_from_source: true
+ OS: windows
+
+ steps:
+ # Git rewrites line endings on windows by default, which turns every
+ # shell script the build is made of into one bash cannot read, and
+ # every name in patches/series into one with a stray return.
+ - name: Keep line endings as they are in the repository
+ run: git config --global core.autocrlf false
+
+ - name: Strip update/ and v from tag and set major version
+ run: |
+ version=${TAG#update/}
+ version=${version#v}
+ version=4${version:1}
+ echo "VERSION=$version" >> $GITHUB_ENV
+
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+ with:
+ submodules: true
+ # When an update/ branch is merged, a release is automatically created
+ # which requires secrets.
+ allow-unsafe-pr-checkout: true
+
+ # quilt has no windows build. The patches are ordinary -p1 diffs
+ # against the repository root, so git applies them in series order.
+ - name: Apply patches
+ run: |
+ while read -r patch; do
+ case "$patch" in '' | '#'*) continue ;; esac
+ echo "applying $patch"
+ git apply --whitespace=nowarn "patches/$patch"
+ done < patches/series
+
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
+ with:
+ node-version-file: .node-version
+ cache: npm
+ cache-dependency-path: |
+ package-lock.json
+ test/package-lock.json
+
+ # npm hands every script it runs to cmd, which cannot run the shell
+ # scripts this repository is built out of. Point it at the same bash
+ # the steps here use rather than at a path, which moves between
+ # images.
+ - name: Let npm run shell scripts
+ run: echo "npm_config_script_shell=$(cygpath -w "$(command -v bash)")" >> $GITHUB_ENV
+
+ # The build merges json by handing jq a process substitution, which
+ # bash presents as a file under /dev/fd. The jq on this image is a
+ # windows program and cannot open those, so it reads the second input
+ # as nothing and the merge fails. Both the product and the package
+ # merge go through here.
+ - name: Let jq read what bash hands it
+ run: |
+ mkdir -p "$RUNNER_TEMP/shim"
+ cat > "$RUNNER_TEMP/shim/jq" <<'SHIM'
+ #!/usr/bin/env bash
+ set -euo pipefail
+ args=()
+ for arg in "$@"; do
+ case $arg in
+ /dev/fd/* | /proc/*/fd/*)
+ copy=$(mktemp)
+ cat "$arg" > "$copy"
+ args+=("$copy")
+ ;;
+ *) args+=("$arg") ;;
+ esac
+ done
+ exec jq.exe "${args[@]}"
+ SHIM
+ chmod +x "$RUNNER_TEMP/shim/jq"
+ echo "$RUNNER_TEMP/shim" >> $GITHUB_PATH
+
+ # Stamping version details into the native binaries clears any
+ # signature they arrived with and asks signtool whether there is one.
+ # That only reads and removes, so it wants no certificate and signs
+ # nothing. It just has to be findable, and the sdk carrying it is not
+ # on the path.
+ - name: Put signtool on the path
+ run: |
+ sdk=$(ls -d "/c/Program Files (x86)/Windows Kits/10/bin"/*/x64 | sort -V | tail -1)
+ test -x "$sdk/signtool.exe"
+ cygpath -w "$sdk" >> $GITHUB_PATH
+
+ # build-release.sh copies the tree with rsync, which neither windows
+ # nor the git bash on this image has. MSYS2 is already here, just not
+ # on the path.
+ - name: Install rsync
+ shell: cmd
+ run: C:\msys64\usr\bin\pacman -Sy --noconfirm --needed rsync
+
+ # Only rsync crosses over. Putting msys2's /usr/bin in front instead
+ # breaks the release step: npm on the path is a shell script whose
+ # shebang reads /usr/bin/env bash, so with msys2 first it is msys2's
+ # bash that runs it, and crossing into a second msys runtime does not
+ # carry the environment. npm then sees no script-shell and falls back
+ # to cmd, which cannot run ./ci/build/build-release.sh, and
+ # KEEP_MODULES is dropped on the way. A forwarder avoids the whole
+ # class: rsync is a native exe that loads its runtime from beside
+ # itself, and nothing else on the path moves.
+ - name: Reach rsync without moving the path
+ run: |
+ cat > "$RUNNER_TEMP/shim/rsync" <<'SHIM'
+ #!/usr/bin/env bash
+ exec /c/msys64/usr/bin/rsync.exe "$@"
+ SHIM
+ chmod +x "$RUNNER_TEMP/shim/rsync"
+
+ - run: npm ci
+ - run: npm run build
+ - run: npm run build:vscode
+ - run: KEEP_MODULES=1 npm run release
+
+ # Of the two tars on this image it is git bash's GNU one that can
+ # rename the tree's top directory as it archives; the windows bsdtar
+ # is built without substitution support. Asserted rather than
+ # assumed, since the two are interchangeable everywhere except here.
+ - name: Package
+ run: |
+ case "$(tar --version | head -1)" in
+ *GNU*) ;;
+ *) echo "expected GNU tar for --transform, got $(tar --version | head -1)" >&2; exit 1 ;;
+ esac
+ npm run package
+
+ - uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
+ with:
+ draft: true
+ discussion_category_name: "📣 Announcements"
+ files: ./release-packages/*
+ tag_name: v${{ env.VERSION }}
+ name: v${{ env.VERSION }}
diff --git a/.github/workflows/scripts.yaml b/.github/workflows/scripts.yaml
new file mode 100644
index 000000000000..180975866b12
--- /dev/null
+++ b/.github/workflows/scripts.yaml
@@ -0,0 +1,67 @@
+name: Script unit tests
+
+on:
+ push:
+ branches:
+ - main
+ paths:
+ - "**.sh"
+ - "**.bats"
+ pull_request:
+ branches:
+ - main
+ paths:
+ - "**.sh"
+ - "**.bats"
+
+permissions:
+ actions: none
+ checks: none
+ contents: read
+ deployments: none
+ issues: none
+ packages: none
+ pull-requests: none
+ repository-projects: none
+ security-events: none
+ statuses: none
+
+# Cancel in-progress runs for pull requests when developers push
+# additional changes, and serialize builds in branches.
+# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-concurrency-to-cancel-any-in-progress-job-or-run
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
+
+jobs:
+ test:
+ name: Run script unit tests
+ runs-on: ubuntu-latest
+ # This runs on Alpine to make sure we're testing with actual sh.
+ container: "alpine:3.17"
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+
+ - name: Install test utilities
+ run: apk add bats checkbashisms
+
+ - name: Check Bashisms
+ run: checkbashisms ./install.sh
+
+ - name: Run script unit tests
+ run: ./ci/dev/test-scripts.sh
+
+ lint:
+ name: Lint shell files
+ runs-on: ubuntu-latest
+ timeout-minutes: 5
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+
+ - name: Install lint utilities
+ run: sudo apt install shellcheck
+
+ - name: Lint shell files
+ run: ./ci/dev/lint-scripts.sh
diff --git a/.github/workflows/security.yaml b/.github/workflows/security.yaml
new file mode 100644
index 000000000000..362b68a9dccb
--- /dev/null
+++ b/.github/workflows/security.yaml
@@ -0,0 +1,92 @@
+name: Security
+
+on:
+ push:
+ branches: [main]
+ paths:
+ - "package.json"
+ pull_request:
+ paths:
+ - "package.json"
+ schedule:
+ # Runs every Monday morning PST
+ - cron: "17 15 * * 1"
+
+# Cancel in-progress runs for pull requests when developers push additional
+# changes, and serialize builds in branches.
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
+
+jobs:
+ audit:
+ name: Audit node modules
+ runs-on: ubuntu-latest
+ timeout-minutes: 15
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+ with:
+ fetch-depth: 0
+
+ - name: Install Node.js
+ uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
+ with:
+ node-version-file: .node-version
+
+ - name: Audit npm for vulnerabilities
+ run: npm audit
+ if: success()
+
+ trivy-scan-repo:
+ name: Scan repo with Trivy
+ permissions:
+ contents: read # for actions/checkout to fetch code
+ security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
+ runs-on: ubuntu-22.04
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+ with:
+ fetch-depth: 0
+
+ - name: Run Trivy vulnerability scanner in repo mode
+ uses: aquasecurity/trivy-action@d2a0b60797ff03db6132bd4e2b293f9b37081297 # latest
+ with:
+ scan-type: "fs"
+ scan-ref: "."
+ ignore-unfixed: true
+ format: "template"
+ template: "@/contrib/sarif.tpl"
+ output: "trivy-repo-results.sarif"
+ severity: "HIGH,CRITICAL"
+
+ - name: Upload Trivy scan results to GitHub Security tab
+ uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4
+ with:
+ sarif_file: "trivy-repo-results.sarif"
+
+ codeql-analyze:
+ permissions:
+ actions: read # for github/codeql-action/init to get workflow details
+ contents: read # for actions/checkout to fetch code
+ security-events: write # for github/codeql-action/autobuild to send a status report
+ name: Analyze with CodeQL
+ runs-on: ubuntu-22.04
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
+ with:
+ config-file: ./.github/codeql-config.yml
+ languages: javascript
+
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
diff --git a/.github/workflows/trivy-docker.yaml b/.github/workflows/trivy-docker.yaml
new file mode 100644
index 000000000000..7ad57f8dc34f
--- /dev/null
+++ b/.github/workflows/trivy-docker.yaml
@@ -0,0 +1,63 @@
+name: Trivy Nightly Docker Scan
+
+on:
+ # Run scans if the workflow is modified, in order to test the
+ # workflow itself. This results in some spurious notifications,
+ # but seems okay for testing.
+ pull_request:
+ branches:
+ - main
+ paths:
+ - .github/workflows/trivy-docker.yaml
+
+ # Run scans against master whenever changes are merged.
+ push:
+ branches:
+ - main
+ paths:
+ - .github/workflows/trivy-docker.yaml
+
+ schedule:
+ - cron: "15 10 * * *"
+
+ workflow_dispatch:
+
+permissions:
+ actions: none
+ checks: none
+ contents: read
+ deployments: none
+ issues: none
+ packages: none
+ pull-requests: none
+ repository-projects: none
+ security-events: write
+ statuses: none
+
+# Cancel in-progress runs for pull requests when developers push
+# additional changes, and serialize builds in branches.
+# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-concurrency-to-cancel-any-in-progress-job-or-run
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+
+jobs:
+ trivy-scan-image:
+ runs-on: ubuntu-22.04
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+
+ - name: Run Trivy vulnerability scanner in image mode
+ uses: aquasecurity/trivy-action@d2a0b60797ff03db6132bd4e2b293f9b37081297 # latest
+ with:
+ image-ref: "docker.io/codercom/code-server:latest"
+ ignore-unfixed: true
+ format: "sarif"
+ output: "trivy-image-results.sarif"
+ severity: "HIGH,CRITICAL"
+
+ - name: Upload Trivy scan results to GitHub Security tab
+ uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4
+ with:
+ sarif_file: "trivy-image-results.sarif"
diff --git a/.github/workflows/update.yaml b/.github/workflows/update.yaml
new file mode 100644
index 000000000000..b54826c79f70
--- /dev/null
+++ b/.github/workflows/update.yaml
@@ -0,0 +1,72 @@
+name: Update code-server
+
+on:
+ workflow_dispatch:
+ inputs:
+ version:
+ type: string
+ required: true
+ schedule:
+ - cron: "0 16,21 * * *"
+
+jobs:
+ update:
+ runs-on: ubuntu-latest
+ env:
+ TAG: ${{ inputs.version }}
+ GH_TOKEN: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
+
+ steps:
+ - name: Fetch latest tag
+ if: env.TAG == ''
+ run: |
+ tag=$(curl -fsSLI -o /dev/null -w "%{url_effective}" https://github.com/microsoft/vscode/releases/latest)
+ tag="${tag#https://github.com/microsoft/vscode/releases/tag/}"
+ echo "TAG=$tag" >> $GITHUB_ENV
+
+ - name: Remove leading v from tag
+ run: |
+ echo "VERSION=${TAG#v}" >> $GITHUB_ENV
+
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+ with:
+ submodules: true
+
+ - name: Check current version
+ id: check
+ run: |
+ commit="$(git -C lib/vscode rev-parse HEAD)"
+ if [[ $(git -C lib/vscode ls-remote --tags | grep "$commit") == */"$VERSION" ]] ; then
+ echo "$VERSION update has already been merged into $(git rev-parse --abbrev-ref HEAD)"
+ echo done=true >> $GITHUB_OUTPUT
+ elif git ls-remote --exit-code --heads origin "update/$VERSION" ; then
+ echo "There is already a PR for updating to $VERSION"
+ echo done=true >> $GITHUB_OUTPUT
+ else
+ echo "$VERSION update has not started yet"
+ echo done=false >> $GITHUB_OUTPUT
+ fi
+
+ - uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # latest
+ if: steps.check.outputs.done == 'false'
+ with:
+ packages: quilt
+ version: 1.0
+
+ - run: ./ci/build/update-vscode.sh
+ if: steps.check.outputs.done == 'false'
+
+ - name: Open PR
+ if: steps.check.outputs.done == 'false'
+ run: |
+ git config --global user.name cdrci
+ git config --global user.email opensource@coder.com
+ git checkout -b "update/$VERSION"
+ git add .
+ git commit -m "Update Code to $VERSION"
+ git push -u origin "$(git branch --show)"
+ gh pr create \
+ --repo coder/code-server \
+ --title "Update Code to $VERSION" \
+ --body-file .cache/checklist \
+ --draft
diff --git a/.gitignore b/.gitignore
index 92c07dafd5a5..7fea491b82ac 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,24 @@
+.tsbuildinfo
+.cache
+/out*/
+release/
+release-packages/
+release-gcp/
+release-images/
node_modules
-build
-release
+/plugins
+/lib/coder-cloud-agent
+.home
+coverage
+**/.DS_Store
+*.bak
+
+# Code packages itself here.
+/lib/vscode-reh-web-*
+
+# Failed e2e test videos are saved here
+test/test-results
+
+# Quilt's internal data.
+/.pc
+/patches/*.diff~
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 000000000000..9854a1b1dd30
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "lib/vscode"]
+ path = lib/vscode
+ url = https://github.com/microsoft/vscode
diff --git a/.node-version b/.node-version
index 5007551bf8c7..df6ae3370f9f 100644
--- a/.node-version
+++ b/.node-version
@@ -1 +1 @@
-10.16.0
+24.21.0
diff --git a/.npmrc b/.npmrc
deleted file mode 100644
index 5fca0d518be7..000000000000
--- a/.npmrc
+++ /dev/null
@@ -1 +0,0 @@
-scripts-prepend-node-path=true
diff --git a/.nvmrc b/.nvmrc
new file mode 120000
index 000000000000..070266a2687d
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+.node-version
\ No newline at end of file
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 000000000000..40cfb028f4d0
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,8 @@
+lib
+release-packages
+release
+helm-chart
+test/scripts
+test/e2e/extensions/test-extension
+.pc
+package-lock.json
diff --git a/.prettierrc.yaml b/.prettierrc.yaml
new file mode 100644
index 000000000000..b6114bf4613b
--- /dev/null
+++ b/.prettierrc.yaml
@@ -0,0 +1,6 @@
+printWidth: 120
+semi: false
+trailingComma: all
+arrowParens: always
+singleQuote: false
+useTabs: false
diff --git a/.tours/contributing.tour b/.tours/contributing.tour
new file mode 100644
index 000000000000..aaff2b500c99
--- /dev/null
+++ b/.tours/contributing.tour
@@ -0,0 +1,151 @@
+{
+ "$schema": "https://aka.ms/codetour-schema",
+ "title": "Contributing",
+ "steps": [
+ {
+ "directory": "src",
+ "line": 1,
+ "description": "Hello world! code-server's source code lives here in `src` (see the explorer). It's broadly arranged into browser code, Node code, and code shared between both."
+ },
+ {
+ "file": "src/node/entry.ts",
+ "line": 157,
+ "description": "code-server begins execution here. CLI arguments are parsed, special flags like --help are handled, then the HTTP server is started."
+ },
+ {
+ "file": "src/node/cli.ts",
+ "line": 28,
+ "description": "This describes all of the code-server CLI options and how they will be parsed."
+ },
+ {
+ "file": "src/node/cli.ts",
+ "line": 233,
+ "description": "Here's the actual CLI parser."
+ },
+ {
+ "file": "src/node/settings.ts",
+ "line": 1,
+ "description": "code-server maintains a settings file that is read and written here."
+ },
+ {
+ "file": "src/node/app.ts",
+ "line": 11,
+ "description": "The core of code-server are HTTP and web socket servers which are created here. They provide authentication, file access, an API, and serve web-based applications like VS Code."
+ },
+ {
+ "file": "src/node/wsRouter.ts",
+ "line": 38,
+ "description": "This is an analog to Express's Router that handles web socket routes."
+ },
+ {
+ "file": "src/node/http.ts",
+ "line": 1,
+ "description": "This file provides various HTTP utility functions."
+ },
+ {
+ "file": "src/node/coder_cloud.ts",
+ "line": 9,
+ "description": "The cloud agent spawned here provides the --link functionality."
+ },
+ {
+ "file": "src/node/heart.ts",
+ "line": 7,
+ "description": "code-server's heart beats to indicate recent activity.\n\nAlso documented here: [https://github.com/coder/code-server/blob/main/docs/FAQ.md#heartbeat-file](https://github.com/coder/code-server/blob/main/docs/FAQ.md#heartbeat-file)"
+ },
+ {
+ "file": "src/node/socket.ts",
+ "line": 13,
+ "description": "We pass sockets to child processes, however we can't pass TLS sockets so when code-server is handling TLS (via --cert) we use this to create a proxy that can be passed to the child."
+ },
+ {
+ "directory": "src/node/routes",
+ "line": 1,
+ "description": "code-server's routes live here in `src/node/routes` (see the explorer)."
+ },
+ {
+ "file": "src/node/routes/index.ts",
+ "line": 123,
+ "description": "The architecture of code-server allows it to be extended with applications via plugins. Each application is registered at its own route and handles requests at and below that route. Currently we have only VS Code (although it is not yet actually split out into a plugin)."
+ },
+ {
+ "file": "src/node/plugin.ts",
+ "line": 103,
+ "description": "The previously mentioned plugins are loaded here."
+ },
+ {
+ "file": "src/node/routes/apps.ts",
+ "line": 12,
+ "description": "This provides a list of the applications registered with code-server."
+ },
+ {
+ "file": "src/node/routes/domainProxy.ts",
+ "line": 18,
+ "description": "code-server provides a built-in proxy to help in developing web-based applications. This is the code for the domain-based proxy.\n\nAlso documented here: [https://github.com/coder/code-server/blob/main/docs/FAQ.md#how-do-i-securely-access-web-services](https://github.com/coder/code-server/blob/main/docs/FAQ.md#how-do-i-securely-access-web-services)"
+ },
+ {
+ "file": "src/node/routes/pathProxy.ts",
+ "line": 19,
+ "description": "Here is the path-based version of the proxy.\n\nAlso documented here: [https://github.com/coder/code-server/blob/main/docs/FAQ.md#how-do-i-securely-access-web-services](https://github.com/coder/code-server/blob/main/docs/FAQ.md#how-do-i-securely-access-web-services)"
+ },
+ {
+ "file": "src/node/proxy.ts",
+ "line": 4,
+ "description": "Both the domain and path proxy use the single proxy instance created here."
+ },
+ {
+ "file": "src/node/routes/health.ts",
+ "line": 5,
+ "description": "A simple endpoint that lets you see if code-server is up.\n\nAlso documented here: [https://github.com/coder/code-server/blob/main/docs/FAQ.md#healthz-endpoint](https://github.com/coder/code-server/blob/main/docs/FAQ.md#healthz-endpoint)"
+ },
+ {
+ "file": "src/node/routes/login.ts",
+ "line": 46,
+ "description": "code-server supports a password-based login here."
+ },
+ {
+ "file": "src/node/routes/static.ts",
+ "line": 16,
+ "description": "This serves static assets. Anything under the code-server directory can be fetched. Anything outside requires authentication."
+ },
+ {
+ "file": "src/node/routes/update.ts",
+ "line": 10,
+ "description": "This endpoint lets you query for the latest code-server version. It's used to power the update popup you see in VS Code."
+ },
+ {
+ "file": "src/node/routes/vscode.ts",
+ "line": 15,
+ "description": "This is the endpoint that serves VS Code's HTML, handles VS Code's websockets, and handles a few VS Code-specific endpoints for fetching static files."
+ },
+ {
+ "file": "src/node/vscode.ts",
+ "line": 13,
+ "description": "The actual VS Code spawn and initialization is handled here. VS Code runs in a separate child process. We communicate via IPC and by passing it web sockets."
+ },
+ {
+ "file": "src/browser/serviceWorker.ts",
+ "line": 1,
+ "description": "The service worker only exists to provide PWA functionality."
+ },
+ {
+ "directory": "src/browser/pages",
+ "line": 1,
+ "description": "HTML, CSS, and JavaScript for each page lives in here `src/browser/pages` (see the explorer). Currently our HTML uses a simple search and replace template system with variables that {{LOOK_LIKE_THIS}}."
+ },
+ {
+ "file": "src/browser/pages/vscode.html",
+ "line": 1,
+ "description": "The VS Code HTML is based off VS Code's own `workbench.html`."
+ },
+ {
+ "directory": "src/browser/media",
+ "line": 1,
+ "description": "Static images and the manifest live here in `src/browser/media` (see the explorer)."
+ },
+ {
+ "directory": "lib/vscode",
+ "line": 1,
+ "description": "code-server makes use of VS Code's frontend web/remote support. Most of the modifications implement the remote server since that portion of the code is closed source and not released with VS Code.\n\nWe also have a few bug fixes and have added some features (like client-side extensions). See [https://github.com/coder/code-server/blob/main/docs/CONTRIBUTING.md#modifications-to-vs-code](https://github.com/coder/code-server/blob/main/docs/CONTRIBUTING.md#modifications-to-vs-code) for a list.\n\nWe make an effort to keep the modifications as few as possible."
+ }
+ ]
+}
diff --git a/.tours/start-development.tour b/.tours/start-development.tour
new file mode 100644
index 000000000000..999adba06125
--- /dev/null
+++ b/.tours/start-development.tour
@@ -0,0 +1,26 @@
+{
+ "$schema": "https://aka.ms/codetour-schema",
+ "title": "Start Development",
+ "steps": [
+ {
+ "file": "package.json",
+ "line": 31,
+ "description": "## Commands\n\nTo start developing, make sure you have Node 16+ and the [required dependencies](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites) installed. Then, run the following commands:\n\n1. Install dependencies:\n>> npm\n\n3. Start development mode (and watch for changes):\n>> npm run watch"
+ },
+ {
+ "file": "src/node/app.ts",
+ "line": 68,
+ "description": "## Visit the web server\n\nIf all goes well, you should see something like this in your terminal. code-server should be live in development mode.\n\n---\n```bash\n[2020-12-09T21:03:37.156Z] info code-server 3.7.4 development\n[2020-12-09T21:03:37.157Z] info Using user-data-dir ~/.local/share/code-server\n[2020-12-09T21:03:37.165Z] info Using config file ~/.config/code-server/config.yaml\n[2020-12-09T21:03:37.165Z] info HTTP server listening on http://127.0.0.1:8080 \n[2020-12-09T21:03:37.165Z] info - Authentication is enabled\n[2020-12-09T21:03:37.165Z] info - Using password from ~/.config/code-server/config.yaml\n[2020-12-09T21:03:37.165Z] info - Not serving HTTPS\n```\n\n---\n\nIf you have the default configuration, you can access it at [http://localhost:8080](http://localhost:8080)."
+ },
+ {
+ "file": "src/browser/pages/login.html",
+ "line": 26,
+ "description": "## Make a change\n\nThis is the login page, let's make a change and see it update on our web server! Perhaps change the text :)\n\n```html\n
Modifying the login page 👨🏼💻
\n```\n\nReminder, you can likely preview at [http://localhost:8080](http://localhost:8080)"
+ },
+ {
+ "file": "src/node/app.ts",
+ "line": 62,
+ "description": "## That's it!\n\n\nThat's all there is to it! When this tour ends, your terminal session may stop, but just use `npm run watch` to start developing from here on out!\n\n\nIf you haven't already, be sure to check out these resources:\n- [Tour: Contributing](command:codetour.startTourByTitle?[\"Contributing\"])\n- [Docs: FAQ.md](https://github.com/coder/code-server/blob/main/docs/FAQ.md)\n- [Docs: CONTRIBUTING.md](https://github.com/coder/code-server/blob/main/docs/CONTRIBUTING.md)\n- [Community: GitHub Discussions](https://github.com/coder/code-server/discussions)\n- [Community: Slack](https://community.coder.com)"
+ }
+ ]
+}
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 8b9b003fa063..000000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,80 +0,0 @@
-language: node_js
-node_js:
- - 10.16.0
-services:
- - docker
-
-before_install:
- - export MAJOR_VERSION="2"
- - export VSCODE_VERSION="1.38.1"
- - export VERSION="$MAJOR_VERSION.$TRAVIS_BUILD_NUMBER"
- - export TAG="$VERSION-vsc$VSCODE_VERSION"
- - if [[ "$TRAVIS_BRANCH" == "master" ]]; then export MINIFY="true"; fi
- - if [[ "$TRAVIS_BRANCH" == "master" ]]; then export PACKAGE="true"; fi
-
-# Don't build on tags because we'll already have built the commit.
-jobs:
- include:
- - name: "Linux build"
- os: linux
- dist: trusty
- env: TARGET="linux"
- if: tag IS blank
- script: scripts/ci.bash
- - name: "Alpine build"
- os: linux
- dist: trusty
- env: TARGET="alpine"
- if: tag IS blank
- script: scripts/ci.bash
- - name: "MacOS build"
- os: osx
- if: tag IS blank
- script: travis_wait 30 scripts/ci.bash
- - name: "Docker build"
- os: linux
- dist: trusty
- env: DOCKER_BUILD="true"
- if: branch == master AND tag IS blank
- script: docker build --build-arg githubToken="$GITHUB_TOKEN" --build-arg codeServerVersion="$VERSION" --build-arg vscodeVersion="$VSCODE_VERSION" -t codercom/code-server:"$TAG" -t codercom/code-server:v2 .
-
-git:
- depth: 3
-
-before_deploy:
- - echo "$TAG" "$TRAVIS_COMMIT"
- - git config --local user.name "$USER_NAME"
- - git config --local user.email "$USER_EMAIL"
- - if ! git tag "$TAG" "$TRAVIS_COMMIT" ; then echo "$TAG already exists"; fi
- - if [[ -n "$DOCKER_BUILD" ]] ; then echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin ; fi
-
-deploy:
- - provider: releases
- file_glob: true
- draft: true
- tag_name: "$TAG"
- target_commitish: "$TRAVIS_COMMIT"
- name: "$TAG"
- skip_cleanup: true
- api_key:
- secure: YL/x24KjYjgYXPcJWk3FV7FGxI79Mh6gBECQEcdlf3fkLEoKFVgzHBoUNWrFPzyR4tgLyWNAgcpD9Lkme1TRWTom7UPjXcwMNyLcLa+uec7ciSAnYD9ntLTpiCuPDD1u0LtRGclSi/EHQ+F8YVq+HZJpXTsJeAmOmihma3GVbGKSZr+BRum+0YZSG4w+o4TOlYzw/4bLWS52MogZcwpjd+hemBbgXLuGU2ziKv2vEKCZFbEeA16II4x1WLI4mutDdCeh7+3aLzGLwDa49NxtsVYNjyNFF75JhCTCNA55e2YMiLz9Uq69IXe/mi5F7xUaFfhIqqLNyKBnKeEOzu3dYnc+8n3LjnQ+00PmkF05nx9kBn3UfV1kwQGh6QbyDmTtBP07rtUMyI14aeQqHjxsaVRdMnwj9Q2DjXRr8UDqESZF0rmK3pHCXS2fBhIzLE8tLVW5Heiba2pQRFMHMZW+KBE97FzcFh7is90Ait3T8enfcd/PWFPYoBejDAdjwxwOkezh5N5ZkYquEfDYuWrFi6zRFCktsruaAcA+xGtTf9oilBBzUqu8Ie+YFWH5me83xakcblJWdaW/D2rLJAJH3m6LFm8lBqyUgDX5t/etob6CpDuYHu5D1J3XINOj/+aLAcadq6qlh70PMZS3zYffUu3JlzaD2amlSHIT8b5YXFc=
- file:
- - release/*.tar.gz
- - release/*.zip
- on:
- repo: cdr/code-server
- branch: master
-
- - provider: script
- skip_cleanup: true
- script: docker push codercom/code-server:"$TAG" ; docker push codercom/code-server:v2
- on:
- repo: cdr/code-server
- branch: master
- condition: -n "$DOCKER_BUILD"
-
-cache:
- yarn: true
- timeout: 1000
- directories:
- - .cache
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 000000000000..e86bd3bea33c
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,1653 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+
+
+## Unreleased
+
+## [4.141.0](https://github.com/coder/code-server/releases/tag/v4.141.0) - 2026-10-08
+
+Code v1.141.0
+
+### Added
+
+- A new `--enable-remote-storage` flag can be used to make code-server persist
+ workbench storage on the remote server instead of browser storage. Use this if
+ you want to share storage between multiple devices.
+
+### Fixed
+
+- The Typescript extension was trying to load as a browser extension even though
+ we build the remote server version, causing it to fail to activate.
+
+### Changed
+
+- Update to Code 1.141.0
+
+## [4.140.0](https://github.com/coder/code-server/releases/tag/v4.140.0) - 2026-10-02
+
+Code v1.140.0
+
+### Changed
+
+- Update to Code 1.140.0
+
+## [4.139.1](https://github.com/coder/code-server/releases/tag/v4.139.1) - 2026-09-26
+
+Code v1.139.1
+
+### Changed
+
+- Update to Code 1.139.1
+
+### Fixed
+
+- `--idle-timeout-seconds` was only validated when passed as
+ `--idle-timeout-seconds=`; values of 60 or less passed as
+ `--idle-timeout-seconds ` were silently accepted.
+
+## [4.138.0](https://github.com/coder/code-server/releases/tag/v4.138.0) - 2026-09-19
+
+Code v1.138.0
+
+### Changed
+
+- Update to Code 1.138.0
+
+### Fixed
+
+- Preserve the original path, query parameters, and fragment when rewriting
+ localhost URLs through the port proxy. If `VSCODE_PROXY_URI` has any query
+ parameters or fragments, those will be lost.
+
+## [4.137.0](https://github.com/coder/code-server/releases/tag/v4.137.0) - 2026-09-11
+
+Code v1.137.0
+
+### Changed
+
+- Update to Code 1.137.0
+
+## [4.136.2](https://github.com/coder/code-server/releases/tag/v4.136.2) - 2026-09-08
+
+Code v1.136.1
+
+### Changed
+
+- Update to Code 1.136.1
+
+### Fixed
+
+- 4.136.2 replaces a removed 4.136.1 release that had the data path incorrectly
+ being set to `~/.vscode-server-oss/data`.
+
+## [4.135.0](https://github.com/coder/code-server/releases/tag/v4.135.0) - 2026-08-27
+
+Code v1.135.0
+
+### Changed
+
+- Update to Code 1.135.0
+
+## [4.134.0](https://github.com/coder/code-server/releases/tag/v4.134.0) - 2026-08-24
+
+Code v1.134.0
+
+### Added
+
+- New `--socket-fd` flag that can be used to listen on a file descriptor. In
+ particular, this allows using code-server with systemd's socket activation.
+- New `--vscode-option` repeatable flag that can be used to pass through options
+ to VS Code. It requires `flag=value` or simply `flag` for booleans. For
+ example: `--vscode-option enable-sandbox --vscode-option agents=true`. The
+ `VSCODE_OPTIONS` environment variable may also be used. For example:
+ `VSCODE_OPTIONS="enable-sandbox agents=true"`. Note that code-server simply
+ splits this variable on spaces and is not aware of quoting.
+
+### Changed
+
+- Update to Code 1.134.0
+- Remove `--unsafe-perm` from installation scripts. This flag results in an
+ error when used with npm since v12 and has been a no-op since v7. If you are
+ installing with a version of npm older than v7 as root, installation may not
+ work correctly.
+
+## [4.133.0](https://github.com/coder/code-server/releases/tag/v4.133.0) - 2026-08-17
+
+Code v1.133.0
+
+### Changed
+
+- Update to Code 1.133.0
+
+## [4.132.0](https://github.com/coder/code-server/releases/tag/v4.132.0) - 2026-08-10
+
+Code v1.132.0
+
+### Changed
+
+- Update to Code 1.132.0
+
+### Fixed
+
+- When proxying, cookies were being decoded and re-encoded, which could cause
+ issues for applications that encode differently. Cookies are now passed
+ through unchanged (aside from stripping out code-server's session token).
+
+## [4.131.0](https://github.com/coder/code-server/releases/tag/v4.131.0) - 2026-07-30
+
+Code v1.131.0
+
+### Changed
+
+- Update to Code 1.131.0
+
+## [4.130.0](https://github.com/coder/code-server/releases/tag/v4.130.0) - 2026-07-24
+
+Code v1.130.0
+
+### Changed
+
+- Update to Code 1.130.0
+
+## [4.129.0](https://github.com/coder/code-server/releases/tag/v4.129.0) - 2026-07-17
+
+Code v1.129.0
+
+### Changed
+
+- Update to Code 1.129.0
+
+## [4.128.0](https://github.com/coder/code-server/releases/tag/v4.128.0) - 2026-07-11
+
+Code v1.128.0
+
+### Changed
+
+- Update to Code 1.128.0
+
+## [4.127.0](https://github.com/coder/code-server/releases/tag/v4.127.0) - 2026-07-02
+
+Code v1.127.0
+
+### Changed
+
+- Update to Code 1.127.0
+
+## [4.126.0](https://github.com/coder/code-server/releases/tag/v4.126.0) - 2026-06-24
+
+Code v1.126.0
+
+### Changed
+
+- Update to Code 1.126.0
+
+## [4.125.0](https://github.com/coder/code-server/releases/tag/v4.125.0) - 2026-06-18
+
+Code v1.125.0
+
+### Changed
+
+- Update to Code 1.125.0
+
+## [4.124.2](https://github.com/coder/code-server/releases/tag/v4.124.2) - 2026-06-16
+
+Code v1.124.2
+
+### Security
+
+- Strip code-server's session token from the cookie before proxying to a local
+ port. Previously, when you used built-in password authentication, the cookie
+ would be sent to the local proxied port, which meant if the service was
+ malicious and not already running as your code-server user it could use the
+ cookie to log into code-server and execute commands as your code-server user.
+
+### Changed
+
+- Update to Code 1.124.2
+
+## [4.123.0](https://github.com/coder/code-server/releases/tag/v4.123.0) - 2026-06-03
+
+Code v1.123.0
+
+### Changed
+
+- Update to Code 1.123.0
+- Microsoft dropped support for armhf remotes so there will no longer be any
+ builds for armhf.
+
+## [4.122.1](https://github.com/coder/code-server/releases/tag/v4.122.1) - 2026-06-02
+
+Code v1.122.1
+
+### Changed
+
+- Update to Code 1.122.1
+
+## [4.122.0](https://github.com/coder/code-server/releases/tag/v4.122.0) - 2026-05-29
+
+Code v1.122.0
+
+### Changed
+
+- Update to Code 1.122.0
+
+### Fixed
+
+- `--app-name` will now affect window titles within the editor (it is now used
+ as the value for `${appName}` in the title template) as well as some other
+ places like the help > about dialog.
+
+### Added
+
+- App name can now be set with the `CODE_SERVER_APP_NAME` environment variable.
+
+## [4.121.0](https://github.com/coder/code-server/releases/tag/v4.121.0) - 2026-05-20
+
+Code v1.121.0
+
+### Changed
+
+- Update to Code 1.121.0
+
+## [4.118.0](https://github.com/coder/code-server/releases/tag/v4.118.0) - 2026-05-06
+
+Code v1.118.0
+
+### Changed
+
+- Update to Code 1.118.0
+
+## [4.117.0](https://github.com/coder/code-server/releases/tag/v4.117.0) - 2026-04-22
+
+Code v1.117.0
+
+### Changed
+
+- Update to Code 1.117.0
+
+## [4.116.0](https://github.com/coder/code-server/releases/tag/v4.116.0) - 2026-04-16
+
+Code v1.116.0
+
+### Changed
+
+- Update to Code 1.116.0
+
+## [4.115.0](https://github.com/coder/code-server/releases/tag/v4.115.0) - 2026-04-08
+
+Code v1.115.0
+
+### Changed
+
+- Update to Code 1.115.0
+
+## [4.114.1](https://github.com/coder/code-server/releases/tag/v4.114.1) - 2026-04-06
+
+Code v1.114.0
+
+### Changed
+
+- Ensure native modules are built from source so they use the correct version of
+ glibc. This should bring down the requirement from 2.34 back down to 2.28.
+
+## [4.114.0](https://github.com/coder/code-server/releases/tag/v4.114.0) - 2026-04-04
+
+Code v1.114.0
+
+### Changed
+
+- Update to Code 1.114.0.
+
+## [4.113.1](https://github.com/coder/code-server/releases/tag/v4.113.1) - 2026-04-03
+
+Code v1.113.0
+
+This is a re-release of v4.113.0 but with the correct Node binaries for arm64
+and armv7l. Previously they were packaging the amd64 Node binary due to a
+mistake while refactoring CI to use more of the upstream build scripts.
+
+## [4.113.0](https://github.com/coder/code-server/releases/tag/v4.113.0) - 2026-04-02
+
+Code v1.113.0
+
+### Changed
+
+- Update to Code 1.113.0
+
+## [4.112.0](https://github.com/coder/code-server/releases/tag/v4.112.0) - 2026-03-19
+
+Code v1.112.0
+
+### Changed
+
+- Update to Code 1.112.0
+
+## [4.111.0](https://github.com/coder/code-server/releases/tag/v4.111.0) - 2026-03-11
+
+Code v1.111.0
+
+### Changed
+
+- Update to Code 1.111.0
+- `--app-name` now affects the error page title.
+
+## [4.110.1](https://github.com/coder/code-server/releases/tag/v4.110.1) - 2026-03-10
+
+Code v1.110.1
+
+### Changed
+
+- Update to Code 1.110.1
+
+## [4.110.0](https://github.com/coder/code-server/releases/tag/v4.110.0) - 2026-03-09
+
+Code v1.110.0
+
+### Changed
+
+- Update to Code 1.110.0
+
+## [4.109.5](https://github.com/coder/code-server/releases/tag/v4.109.5) - 2026-03-02
+
+Code v1.109.5
+
+### Changed
+
+- Update to Code 1.109.5
+
+## [4.109.2](https://github.com/coder/code-server/releases/tag/v4.109.2) - 2026-02-12
+
+Code v1.109.2
+
+### Changed
+
+- Update to Code 1.109.2
+
+## [4.109.0](https://github.com/coder/code-server/releases/tag/v4.109.0) - 2026-02-12
+
+Code v1.109.0
+
+### Changed
+
+- Update to Code 1.109.0
+
+## [4.108.2](https://github.com/coder/code-server/releases/tag/v4.108.2) - 2026-01-26
+
+Code v1.108.2
+
+### Changed
+
+- Update to Code 1.108.2
+
+## [4.108.1](https://github.com/coder/code-server/releases/tag/v4.108.1) - 2026-01-16
+
+Code v1.108.1
+
+### Changed
+
+- Update to Code 1.108.1
+
+## [4.108.0](https://github.com/coder/code-server/releases/tag/v4.108.0) - 2026-01-12
+
+Code v1.108.0
+
+### Changed
+
+- Update to Code 1.108.0
+
+## [4.107.1](https://github.com/coder/code-server/releases/tag/v4.107.1) - 2026-01-09
+
+Code v1.107.1
+
+### Changed
+
+- Update to Code 1.107.1
+
+## [4.107.0](https://github.com/coder/code-server/releases/tag/v4.107.0) - 2026-12-17
+
+Code v1.107.0
+
+### Changed
+
+- Update to Code 1.107.0
+
+### Added
+
+- New `--cookie-suffix` flag that can be used to add a suffix to the cookie when
+ using the built-in password authentication. You can use this to avoid
+ collisions with other instances of code-server.
+- Support a new property `authorizationHeaderToken` on the extension gallery
+ configuration. This will be added to marketplace requests as a bearer token
+ using the `Authorization` header.
+
+## [4.106.3](https://github.com/coder/code-server/releases/tag/v4.106.3) - 2025-12-01
+
+Code v1.106.3
+
+### Changed
+
+- Update to Code 1.106.3
+
+## [4.106.2](https://github.com/coder/code-server/releases/tag/v4.106.2) - 2025-11-19
+
+Code v1.106.2
+
+### Changed
+
+- Update to Code 1.106.2
+
+## [4.106.0](https://github.com/coder/code-server/releases/tag/v4.106.0) - 2025-11-19
+
+Code v1.106.0
+
+### Changed
+
+- Update to Code 1.106.0
+
+## [4.105.1](https://github.com/coder/code-server/releases/tag/v4.105.1) - 2025-10-20
+
+Code v1.105.1
+
+### Changed
+
+- Update to Code 1.105.1
+
+## [4.105.0](https://github.com/coder/code-server/releases/tag/v4.105.0) - 2025-10-17
+
+Code v1.105.0
+
+### Changed
+
+- Update to Code 1.105.0
+
+## [4.104.3](https://github.com/coder/code-server/releases/tag/v4.104.3) - 2025-10-07
+
+Code v1.104.3
+
+### Changed
+
+- Update to Code 1.104.3.
+
+## [4.104.2](https://github.com/coder/code-server/releases/tag/v4.104.2) - 2025-09-26
+
+Code v1.104.2
+
+### Changed
+
+- Update to Code 1.104.2.
+
+## [4.104.1](https://github.com/coder/code-server/releases/tag/v4.104.1) - 2025-09-19
+
+Code v1.104.1
+
+### Changed
+
+- Update to Code 1.104.1.
+
+## [4.104.0](https://github.com/coder/code-server/releases/tag/v4.104.0) - 2025-09-15
+
+Code v1.104.0
+
+### Fixed
+
+- Fix "extension not found" errors from Open VSX when trying to install the
+ latest version of an extension.
+
+### Changed
+
+- Update to Code 1.104.0.
+
+## [4.103.2](https://github.com/coder/code-server/releases/tag/v4.103.2) - 2025-08-25
+
+Code v1.103.2
+
+### Changed
+
+- Update to Code 1.103.2.
+
+## [4.103.1](https://github.com/coder/code-server/releases/tag/v4.103.1) - 2025-08-15
+
+Code v1.103.1
+
+### Changed
+
+- Update to Code 1.103.1.
+
+## [4.103.0](https://github.com/coder/code-server/releases/tag/v4.103.0) - 2025-08-12
+
+Code v1.103.0
+
+### Changed
+
+- Update to Code 1.103.0.
+
+## [4.102.2](https://github.com/coder/code-server/releases/tag/v4.102.2) - 2025-07-24
+
+Code v1.102.2
+
+### Changed
+
+- Update to Code 1.102.2.
+
+## [4.102.1](https://github.com/coder/code-server/releases/tag/v4.102.1) - 2025-07-17
+
+Code v1.102.1
+
+### Changed
+
+- Update to Code 1.102.1.
+
+## [4.102.0](https://github.com/coder/code-server/releases/tag/v4.102.0) - 2025-07-16
+
+Code v1.102.0
+
+### Changed
+
+- Update to Code 1.102.0.
+
+### Added
+
+- Custom strings can be configured using the `--i18n` flag set to a JSON
+ file. This can be used for either translation (and can be used alongside
+ `--locale`) or for customizing the strings. See
+ [./src/node/i18n/locales/en.json](./src/node/i18n/locales/en.json) for the
+ available keys.
+
+## [4.101.2](https://github.com/coder/code-server/releases/tag/v4.101.2) - 2025-06-25
+
+Code v1.101.2
+
+### Changed
+
+- Update to Code 1.101.2.
+
+### Fixed
+
+- Fix web views not loading due to 401 when requesting the service worker.
+
+## [4.101.1](https://github.com/coder/code-server/releases/tag/v4.101.1) - 2025-06-20
+
+Code v1.101.1
+
+### Changed
+
+- Update to Code 1.101.1.
+
+## [4.101.0](https://github.com/coder/code-server/releases/tag/v4.101.0) - 2025-06-20
+
+Code v1.101.0
+
+### Changed
+
+- Update to Code 1.101.0.
+
+## [4.100.3](https://github.com/coder/code-server/releases/tag/v4.100.3) - 2025-06-03
+
+Code v1.100.3
+
+### Changed
+
+- Update to Code 1.100.3.
+
+## [4.100.2](https://github.com/coder/code-server/releases/tag/v4.100.2) - 2025-05-15
+
+Code v1.100.2
+
+### Changed
+
+- Update to Code 1.100.2.
+
+## [4.100.1](https://github.com/coder/code-server/releases/tag/v4.100.1) - 2025-05-13
+
+Code v1.100.1
+
+### Changed
+
+- Update to Code 1.100.1.
+
+## [4.100.0](https://github.com/coder/code-server/releases/tag/v4.100.0) - 2025-05-12
+
+Code v1.100.0
+
+### Added
+
+- Trusted domains for links can now be set at run-time by configuring
+ `linkProtectionTrustedDomains` in the `lib/vscode/product.json` file or via
+ the `--link-protection-trusted-domains` flag.
+
+### Changed
+
+- Update to Code 1.100.0.
+- Disable extension signature verification, which previously was skipped by
+ default (the package used for verification is not available to OSS builds of
+ VS Code) but now reportedly throws hard errors making it impossible to install
+ extensions.
+
+### Fixed
+
+- Flags with repeatable options now work via the config file.
+
+## [4.99.4](https://github.com/coder/code-server/releases/tag/v4.99.4) - 2025-05-02
+
+Code v1.99.3
+
+### Security
+
+- Validate that ports in the path proxy are numbers, to prevent proxying to
+ arbitrary domains.
+
+## [4.99.3](https://github.com/coder/code-server/releases/tag/v4.99.3) - 2025-04-17
+
+Code v1.99.3
+
+### Added
+
+- Added `--skip-auth-preflight` flag to let preflight requests through the
+ proxy.
+
+### Changed
+
+- Update to Code 1.99.3.
+
+## [4.99.2](https://github.com/coder/code-server/releases/tag/v4.99.2) - 2025-04-10
+
+Code v1.99.2
+
+### Changed
+
+- Update to Code 1.99.2.
+
+## [4.99.1](https://github.com/coder/code-server/releases/tag/v4.99.1) - 2025-04-08
+
+Code v1.99.1
+
+### Changed
+
+- Update to Code 1.99.1.
+
+## [4.99.0](https://github.com/coder/code-server/releases/tag/v4.99.0) - 2025-04-07
+
+Code v1.99.0
+
+### Changed
+
+- Update to Code 1.99.0.
+
+## [4.98.0](https://github.com/coder/code-server/releases/tag/v4.98.0) - 2025-03-07
+
+Code v1.98.0
+
+### Changed
+
+- Update to Code 1.98.0.
+
+## [4.97.2](https://github.com/coder/code-server/releases/tag/v4.96.4) - 2025-02-18
+
+Code v1.97.2
+
+### Added
+
+- Added back macOS amd64 builds.
+
+### Changed
+
+- Update to Code 1.97.2.
+- Softened dark mode login page colors.
+
+## [4.96.4](https://github.com/coder/code-server/releases/tag/v4.96.4) - 2025-01-20
+
+Code v1.96.4
+
+### Changed
+
+- Update to Code 1.96.4.
+
+## [4.96.2](https://github.com/coder/code-server/releases/tag/v4.96.2) - 2024-12-20
+
+Code v1.96.2
+
+### Changed
+
+- Update to Code 1.96.2.
+
+## [4.96.1](https://github.com/coder/code-server/releases/tag/v4.96.1) - 2024-12-18
+
+Code v1.96.1
+
+### Added
+
+- Dark color scheme for login and error pages.
+
+### Changed
+
+- Update to Code 1.96.1.
+
+## [4.95.3](https://github.com/coder/code-server/releases/tag/v4.95.3) - 2024-11-18
+
+Code v1.95.3
+
+### Changed
+
+- Update to Code 1.95.3.
+
+## [4.95.2](https://github.com/coder/code-server/releases/tag/v4.95.2) - 2024-11-12
+
+Code v1.95.2
+
+### Changed
+
+- Update to Code 1.95.2.
+
+## [4.95.1](https://github.com/coder/code-server/releases/tag/v4.95.1) - 2024-11-06
+
+Code v1.95.1
+
+### Changed
+
+- Update to Code 1.95.1.
+
+## [4.93.1](https://github.com/coder/code-server/releases/tag/v4.93.1) - 2024-09-23
+
+Code v1.93.1
+
+### Changed
+
+- Updated to Code 1.93.1.
+
+### Added
+
+- Added `--abs-proxy-base-path` flag for when code-server is not at the root.
+
+## [4.92.2](https://github.com/coder/code-server/releases/tag/v4.92.2) - 2024-08-19
+
+Code v1.92.2
+
+### Breaking changes
+
+- Dropped a patch that changed the compile target from es2022 to es2020 because
+ it no longer works with the way VS Code uses static properties. This may break
+ older browsers, so those browsers will either have to be updated or use an
+ older version of code-server.
+
+### Changed
+
+- Updated to Code 1.92.2.
+
+## [4.91.0](https://github.com/coder/code-server/releases/tag/v4.91.0) - 2024-07-10
+
+Code v1.91.0
+
+### Changed
+
+- Updated to Code 1.91.0.
+
+## [4.90.3](https://github.com/coder/code-server/releases/tag/v4.90.3) - 2024-06-21
+
+Code v1.90.2
+
+### Changed
+
+- Updated to Code 1.90.2.
+
+### Fixed
+
+- When the log gets rotated it will no longer incorrectly be moved to a new
+ directory created in the current working directory named with a date.
+ Instead, the file itself is prepended with the date and kept in the same
+ directory, as originally intended.
+
+## [4.90.2](https://github.com/coder/code-server/releases/tag/v4.90.2) - 2024-06-14
+
+Code v1.90.1
+
+### Changed
+
+- Updated to Code 1.90.1.
+
+## [4.90.1](https://github.com/coder/code-server/releases/tag/v4.90.1) - 2024-06-12
+
+Code v1.90.0
+
+### Fixed
+
+- Cache a call to get CPU information used in telemetry that could result in a
+ lack responsiveness if it was particularly slow.
+
+## [4.90.0](https://github.com/coder/code-server/releases/tag/v4.90.0) - 2024-06-11
+
+Code v1.90.0
+
+### Changed
+
+- Updated to Code 1.90.0.
+- Updated Node to 20.11.1.
+
+### Added
+
+- Send contents to the clipboard in the integrated terminal by piping to
+ `code-server --stdin-to-clipboard` or `code-server -c`.
+
+ You may want to make this an alias:
+
+ ```
+ alias xclip="code-server --stdin-to-clipboard"
+ echo -n "hello world" | xclip
+ ```
+
+## [4.89.1](https://github.com/coder/code-server/releases/tag/v4.89.1) - 2024-04-14
+
+Code v1.89.1
+
+### Changed
+
+- Updated to Code 1.89.1.
+
+## [4.89.0](https://github.com/coder/code-server/releases/tag/v4.89.0) - 2024-04-08
+
+Code v1.89.0
+
+### Changed
+
+- Updated to Code 1.89.0.
+
+## [4.23.1](https://github.com/coder/code-server/releases/tag/v4.23.1) - 2024-04-15
+
+Code v1.88.1
+
+### Changed
+
+- Updated to Code 1.88.1.
+
+## [4.23.0](https://github.com/coder/code-server/releases/tag/v4.23.0) - 2024-04-08
+
+Code v1.88.0
+
+### Changed
+
+- Updated to Code 1.88.0.
+- Updated Node to 18.18.2.
+
+### Fixed
+
+- Fix masking the exit code when failing to install extensions on the command
+ line outside the integrated terminal. Installing extensions inside the
+ integrated terminal still masks the exit code and is an upstream bug.
+
+## [4.22.1](https://github.com/coder/code-server/releases/tag/v4.22.1) - 2024-03-14
+
+Code v1.87.2
+
+### Changed
+
+- Updated to Code 1.87.2.
+- Enable keep-alive for proxy agent.
+
+## [4.22.0](https://github.com/coder/code-server/releases/tag/v4.22.0) - 2024-03-03
+
+Code v1.87.0
+
+### Changed
+
+- Updated to Code 1.87.0.
+
+## [4.21.2](https://github.com/coder/code-server/releases/tag/v4.21.2) - 2024-02-28
+
+Code v1.86.2
+
+### Changed
+
+- Updated to Code 1.86.2.
+
+## [4.21.1](https://github.com/coder/code-server/releases/tag/v4.21.1) - 2024-02-09
+
+Code v1.86.1
+
+### Changed
+
+- Updated to Code 1.86.1.
+- Updated to Node 18.17.1.
+
+### Added
+
+- Docker images for Fedora and openSUSE.
+
+## [4.21.0](https://github.com/coder/code-server/releases/tag/v4.21.0) - 2024-02-05
+
+Code v1.86.0
+
+### Changed
+
+- Updated to Code 1.86.0.
+
+## [4.20.1](https://github.com/coder/code-server/releases/tag/v4.20.1) - 2024-01-22
+
+Code v1.85.2
+
+### Changed
+
+- Updated to Code 1.85.2.
+
+### Fixed
+
+- Query variables are no longer double-encoded when going over the path proxy.
+
+## [4.20.0](https://github.com/coder/code-server/releases/tag/v4.20.0) - 2023-12-21
+
+Code v1.85.1
+
+### Added
+
+- New flag `--disable-file-uploads` to disable uploading files to the remote by
+ drag and drop and to disable opening local files via the "show local" button
+ in the file open prompt. Note that you can still open local files by drag and
+ dropping the file onto the editor pane.
+- Added `wget` to the release image.
+
+### Changed
+
+- Updated to Code 1.85.1.
+- The `--disable-file-downloads` flag will now disable the "show local" button
+ in the file save prompt as well.
+- Debian release image updated to use Bookworm.
+
+## [4.19.1](https://github.com/coder/code-server/releases/tag/v4.19.1) - 2023-11-29
+
+Code v1.84.2
+
+### Fixed
+
+- Fixed an issue where parts of the editor would not load (like the file
+ explorer, source control, etc) when using a workspace file.
+
+## [4.19.0](https://github.com/coder/code-server/releases/tag/v4.19.0) - 2023-11-18
+
+Code v1.84.2
+
+### Changed
+
+- Updated to Code 1.84.2.
+
+## [4.18.0](https://github.com/coder/code-server/releases/tag/v4.18.0) - 2023-10-20
+
+Code v1.83.1
+
+### Changed
+
+- Updated to Code 1.83.1.
+
+## [4.17.1](https://github.com/coder/code-server/releases/tag/v4.17.1) - 2023-09-29
+
+Code v1.82.2
+
+### Fixed
+
+- Make secret storage persistent. For example, logging in with GitHub should
+ persist between browser refreshes and code-server restarts.
+- Issues with argon2 on arm builds should be fixed now.
+
+## [4.17.0](https://github.com/coder/code-server/releases/tag/v4.17.0) - 2023-09-22
+
+Code v1.82.2
+
+### Added
+
+- Japanese locale.
+- `CODE_SERVER_HOST` environment variable.
+
+### Changed
+
+- Update to Code 1.82.2. This includes an update to Node 18, which also means
+ that the minimum glibc is now 2.28. If you need to maintain a lower glibc then
+ you can take a version of Node 18 that is compiled with a lower glibc and use
+ that to build code-server (or at a minimum rebuild the native modules).
+- Display paths to config files in full rather than abbreviated. If you have
+ trouble with the password not working please update and make sure the
+ displayed config paths are what you expect.
+
+### Fixed
+
+- Fix some dependency issues for the standalone arm64 and armv7l releases. If
+ you had issues with missing or failing modules please try these new builds.
+
+## [4.16.1](https://github.com/coder/code-server/releases/tag/v4.16.1) - 2023-07-31
+
+Code v1.80.2
+
+### Changed
+
+- Updated to Code 1.80.2.
+
+## [4.16.0](https://github.com/coder/code-server/releases/tag/v4.16.0) - 2023-07-28
+
+Code v1.80.1
+
+### Added
+
+- `--disable-proxy` flag. This disables the domain and path proxies but it does
+ not disable the ports panel in Code. That can be disabled by using
+ `remote.autoForwardPorts=false` in your settings.
+
+## [4.15.0](https://github.com/coder/code-server/releases/tag/v4.15.0) - 2023-07-21
+
+Code v1.80.1
+
+### Changed
+
+- Updated to Code 1.80.1.
+
+### Added
+
+- `--trusted-origin` flag for specifying origins that you trust but do not
+ control (for example a reverse proxy).
+
+Code v1.79.2
+
+## [4.14.1](https://github.com/coder/code-server/releases/tag/v4.14.1) - 2023-06-26
+
+Code v1.79.2
+
+### Security
+
+- Remove extra write permissions on the Node binary bundled with the linux-amd64
+ tarball. If you extract the tar without a umask this could mean the Node
+ binary would be unexpectedly writable.
+
+### Fixed
+
+- Inability to launch multiple instances of code-server for different users.
+
+### Added
+
+- `--session-socket` CLI flag to configure the location of the session socket.
+ By default it will be placed in `/code-server-ipc.sock`.
+
+## [4.14.0](https://github.com/coder/code-server/releases/tag/v4.14.0) - 2023-06-16
+
+Code v1.79.2
+
+### Added
+
+- `--domain-proxy` now supports `{{port}}` and `{{host}}` template variables.
+
+### Changed
+
+- Updated to Code 1.79.2
+- Files opened from an external terminal will now open in the most closely
+ related window rather than in the last opened window.
+
+## [4.13.0](https://github.com/coder/code-server/releases/tag/v4.13.0) - 2023-05-19
+
+Code v1.78.2
+
+### Changed
+
+- Updated to Code 1.78.2.
+
+### Fixed
+
+- Proxying files that contain non-ASCII characters.
+- Origin check when X-Forwarded-Host contains comma-separated hosts.
+
+## [4.12.0](https://github.com/coder/code-server/releases/tag/v4.12.0) - 2023-04-21
+
+Code v1.77.3
+
+### Changed
+
+- Updated to Code 1.77.3
+- Ports panel will use domain-based proxy (instead of the default path-based
+ proxy) when set via --proxy-domain.
+- Apply --app-name to the PWA title.
+
+### Added
+
+- Thai translation for login page.
+- Debug logs around the origin security check. If you are getting forbidden
+ errors on web sockets please run code-server with `--log debug` to see why the
+ requests are being blocked.
+
+## [4.11.0](https://github.com/coder/code-server/releases/tag/v4.11.0) - 2023-03-16
+
+Code v1.76.1
+
+### Changed
+
+- Updated to Code 1.76.1
+
+## [4.10.1](https://github.com/coder/code-server/releases/tag/v4.10.1) - 2023-03-04
+
+Code v1.75.1
+
+### Security
+
+Added an origin check to web sockets to prevent cross-site hijacking attacks on
+users using older or niche browser that do not support SameSite cookies and
+attacks across sub-domains that share the same root domain.
+
+The check requires the host header to be set so if you use a reverse proxy
+ensure it forwards that information otherwise web sockets will be blocked.
+
+## [4.10.0](https://github.com/coder/code-server/releases/tag/v4.10.0) - 2023-02-15
+
+Code v1.75.1
+
+### Changed
+
+- Updated to Code 1.75.1
+
+### Removed
+
+- Removed `--link` (was deprecated over thirteen months ago in 4.0.1).
+
+## [4.9.1](https://github.com/coder/code-server/releases/tag/v4.9.1) - 2022-12-15
+
+Code v1.73.1
+
+### Changed
+
+- Updated a couple steps in the build and release process to ensure we're using
+ `npm` and `yarn` consistently depending on the step.
+
+### Fixed
+
+- Fixed an issue with code-server version not displaying in the Help > About window.
+- Fixed terminal not loading on macOS clients.
+
+## [4.9.0](https://github.com/coder/code-server/releases/tag/v4.9.0) - 2022-12-06
+
+Code v1.73.1
+
+### Changed
+
+- Upgraded to Code 1.73.1
+
+### Added
+
+- `/security.txt` added as a route with info on our security policy information thanks to @ghuntley
+
+### Fixed
+
+- Installing on majaro images should now work thanks to @MrPeacockNLB for
+ adding the `--noconfirm` flag in `install.sh`
+
+### Known Issues
+
+- `--cert` on Ubuntu 22.04: OpenSSL v3 is used which breaks `pem` meaning the
+ `--cert` feature will not work. [Reference](https://github.com/adobe/fetch/pull/318#issuecomment-1306070259)
+
+## [4.8.3](https://github.com/coder/code-server/releases/tag/v4.8.3) - 2022-11-07
+
+Code v1.72.1
+
+### Added
+
+- install script now supports arch-like (i.e. manjaro, endeavourous, etc.)
+ architectures
+
+### Changed
+
+- Updated text in the Getting Started page.
+
+## [4.8.2](https://github.com/coder/code-server/releases/tag/v4.8.2) - 2022-11-02
+
+Code v1.72.1
+
+### Added
+
+- New text in the Getting Started page with info about
+ `coder/coder`. This is enabled by default but can be disabled by passing the CLI
+ flag `--disable-getting-started-override` or setting
+ `CS_DISABLE_GETTING_STARTED_OVERRIDE=1` or
+ `CS_DISABLE_GETTING_STARTED_OVERRIDE=true`.
+
+## [4.8.1](https://github.com/coder/code-server/releases/tag/v4.8.1) - 2022-10-28
+
+Code v1.72.1
+
+### Fixed
+
+- Fixed CSP error introduced in 4.8.0 that caused issues with webviews and most
+ extensions.
+
+## [4.8.0](https://github.com/coder/code-server/releases/tag/v4.8.0) - 2022-10-24
+
+Code v1.72.1
+
+### Added
+
+- Support for the Ports panel which leverages code-server's built-in proxy. It
+ also uses `VSCODE_PROXY_URI` where `{{port}}` is replace when forwarding a port.
+ Example: `VSCODE_PROXY_URI=https://{{port}}.kyle.dev` would forward an
+ application running on localhost:3000 to https://3000.kyle.dev
+- Support for `--disable-workspace-trust` CLI flag
+- Support for `--goto` flag to open file @ line:column
+- Added Ubuntu-based images for Docker releases. If you run into issues with
+ `PATH` being overwritten in Docker please try the Ubuntu image as this is a
+ problem in the Debian base image.
+
+### Changed
+
+- Updated Code to 1.72.1
+
+### Fixed
+
+- Enabled `BROWSER` environment variable
+- Patched `asExternalUri` to work so now extensions run inside code-server can use it
+
+## [4.7.1](https://github.com/coder/code-server/releases/tag/v4.7.1) - 2022-09-30
+
+Code v1.71.2
+
+### Changed
+
+- Updated Code to 1.71.2
+
+### Fixed
+
+- Fixed install script not upgrading code-server when already installed on RPM-based machines
+- Fixed install script failing to gain root permissions on FreeBSD
+
+## [4.7.0](https://github.com/coder/code-server/releases/tag/v4.7.0) - 2022-09-09
+
+Code v1.71.0
+
+### Changed
+
+- Updated Code to 1.71.0
+
+### Removed
+
+- Dropped heartbeat patch because it was implemented upstream
+
+### Fixed
+
+- Add flags --unsafe-perm --legacy-peer-deps in `npm-postinstall.sh` which ensures installing with npm works correctly
+
+## [4.6.1](https://github.com/coder/code-server/releases/tag/v4.6.1) - 2022-09-31
+
+Code v1.70.2
+
+### Changed
+
+- Updated Code to 1.70.2
+- Updated `argon2` to 0.29.0 which should fix issues on FreeBSD
+- Updated docs to suggest using `npm` instead of `yarn`
+
+### Removed
+
+- Dropped database migration patch affected to 4.0.2 versions and earlier.
+
+### Fixed
+
+- Fixed preservation of `process.execArgv` which means you can pass `--prof` to profile code-server
+
+## [4.6.0](https://github.com/coder/code-server/releases/tag/v4.6.0) - 2022-08-17
+
+Code v1.70.1
+
+### Changed
+
+- Updated Code to 1.70.1.
+
+### Added
+
+- Added a heartbeat to sockets. This should prevent them from getting closed by
+ reverse proxy timeouts when idle like NGINX's default 60-second timeout.
+
+### Fixed
+
+- Fixed logout option appearing even when authentication is disabled.
+
+## [4.5.2](https://github.com/coder/code-server/releases/tag/v4.5.2) - 2022-08-15
+
+Code v1.68.1
+
+### Security
+
+- Fixed the proxy route not performing authentication. For example if you were
+ to run a development HTTP server using `python -m http.server 8000` then it
+ would be accessible at `my.domain/proxy/8000/` without any authentication.
+
+ If all of the following apply to you please update as soon as possible:
+ - You run code-server with the built-in password authentication.
+ - You run unprotected HTTP services on ports accessible by code-server.
+
+### Changed
+
+- Invoking `code-server` in the integrated terminal will now use the script that
+ comes with upstream Code. This means flags like `--wait` will be
+ automatically supported now. However the upstream script only has the ability
+ to interact with the running code-server and cannot spawn new instances. If
+ you need to spawn a new code-server from the integrated terminal please
+ specify the full path to code-server's usual script (for example
+ `/usr/bin/code-server`).
+
+### Fixed
+
+- Invoking `code-server` in the integrated terminal will now work instead of
+ erroring about not finding Node.
+
+## [4.5.1](https://github.com/coder/code-server/releases/tag/v4.5.1) - 2022-07-18
+
+Code v1.68.1
+
+### Changed
+
+- We now use `release/v<0.0.0>` for the release branch name so it doesn't
+ conflict with the tag name
+- Added `.prettierignore` to ignore formatting files in `lib/vscode`
+
+### Added
+
+- Allow more comprehensive affinity config in Helm chart
+- Added custom message in Homebrew PR to make sure code-server maintainers are
+ tagged
+- Allow setting `priorityClassName` via Helm chart
+- Added troubleshooting docs to `CONTRIBUTING.md`
+
+### Fixed
+
+- Removed default memory limit which was set via `NODE_OPTIONS`
+- Changed output in pipe to make it easier to debug code-server when doing live
+ edits
+- Fixed display-language patch to use correct path which broke in 4.5.0
+- Fixed multiple code-server windows opening when using the code-server CLI in
+ the Integrated Terminal
+- Fixed Integrated Terminal not working when web base was not the root path
+
+### Security
+
+- Updated `glob-parent` version in dependencies
+
+## [4.5.0](https://github.com/coder/code-server/releases/tag/v4.5.0) - 2022-06-29
+
+Code v1.68.1
+
+### Changed
+
+- Updated codecov to use codecov uploader
+- Moved integration tests to Jest
+- Fixed docker release to only download .deb
+- Upgraded to Code 1.68.1
+- Install `nfpm` from GitHub
+- Upgraded to TypeScript 4.6
+
+### Added
+
+- Added tests for `open`, `isWsl`, `handlePasswordValidation`
+- Provided alternate image registry to dockerhub
+- Allowed users to have scripts run on container with `ENTRYPOINTD` environment
+ variable
+
+### Fixed
+
+- Fixed open CLI command to work on macOS
+
+## [4.4.0](https://github.com/coder/code-server/releases/tag/v4.4.0) - 2022-05-06
+
+Code v1.66.2
+
+### Changed
+
+- Refactored methods in `Heart` class and made `Heart.beat()` async to make
+ testing easier.
+- Upgraded to Code 1.66.2.
+
+### Added
+
+- Added back telemetry patch which was removed in the Code reachitecture.
+- Added support to use `true` for `CS_DISABLE_FILE_DOWNLOADS` environment
+ variable. This means you can disable file downloads by setting
+ `CS_DISABLE_FILE_DOWNLOADS` to `true` or `1`.
+- Added tests for `Heart` class.
+
+### Fixed
+
+- Fixed installation issue in AUR after LICENSE rename.
+- Fixed issue with listening on IPv6 addresses.
+- Fixed issue with Docker publish action not being able to find artifacts. Now
+ it downloads the release assets from the release.
+
+## [4.3.0](https://github.com/coder/code-server/releases/tag/v4.3.0) - 2022-04-14
+
+Code v1.65.2
+
+### Changed
+
+- Excluded .deb files from release Docker image which drops the compressed and
+ uncompressed size by 58% and 34%.
+- Upgraded to Code 1.65.2.
+
+### Added
+
+- Added a new CLI flag called `--disable-file-downloads` which allows you to
+ disable the "Download..." option that shows in the UI when right-clicking on a
+ file. This can also set by running `CS_DISABLE_FILE_DOWNLOADS=1`.
+- Aligned the dependencies for binary and npm release artifacts.
+
+### Fixed
+
+- Fixed the code-server version from not displaying in the Help > About dialog.
+- Fixed issues with the TypeScript and JavaScript Language Features Extension
+ failing to activate.
+- Fixed missing files in ipynb extension.
+- Fixed the homebrew release workflow.
+- Fixed the Docker release workflow from not always publishing version tags.
+
+## [4.2.0](https://github.com/coder/code-server/releases/tag/v4.2.0) - 2022-03-22
+
+Code v1.64.2
+
+### Added
+
+- Added tests for `handleArgsSocketCatchError`, `setDefaults` and
+ `optionDescriptions`.
+
+### Changed
+
+- We switched from using the fork `coder/vscode` to a submodule of
+ `microsoft/vscode` + patches managed by `quilt` for how Code sits inside the
+ code-server codebase.
+- Upgraded to Code 1.64.2.
+
+### Fixed
+
+- Update popup notification through `--disable-update-check` is now fixed.
+- Fixed PWA icons not loading on iPad
+- Fixed the homebrew release process. Our `cdrci` bot should now automatically
+ update the version as part of the release pipeline.
+- Fixed titleBar color setting being ignored in PWA.
+
+### Security
+
+- Updated to `minimist-list`.
+- Updated `cloud-agent` to `v0.2.4` which uses `nhooyr.io/webscoket` `v1.8.7`.
+
+## [4.1.0](https://github.com/coder/code-server/releases/tag/v4.1.0) - 2022-03-03
+
+Code v1.63.0
+
+### Added
+
+- Support for injecting GitHub token into Code so extensions can make use of it.
+ This can be done with the `GITHUB_TOKEN` environment variable or `github-auth`
+ in the config file.
+- New flag `--socket-mode` allows setting the mode (file permissions) of the
+ socket created when using `--socket`.
+- The version of Code bundled with code-server now appears when using the
+ `--version` flag. For example: `4.0.2 5cdfe74686aa73e023f8354a9a6014eb30caa7dd with Code 1.63.0`.
+ If you have been parsing this flag for the version you might want to use
+ `--version --json` instead as doing that will be more stable.
+
+### Changed
+
+- The workspace or folder passed on the CLI will now use the same redirect
+ method that the last opened workspace or folder uses. This means if you use
+ something like `code-server /path/to/dir` you will now get a query parameter
+ added (like so: `my-domain.tld?folder=/path/to/dir`), making it easier to edit
+ by hand and making it consistent with the last opened and menu open behaviors.
+- The folder/workspace query parameter no longer has encoded slashes, making
+ them more readable and editable by hand. This was only affecting the last
+ opened behavior, not opens from the menu.
+
+### Fixed
+
+- Fix web sockets not connecting when using `--cert`.
+- Prevent workspace state collisions when opening a workspace that shares the
+ same file path with another workspace on a different machine that shares the
+ same domain. This was causing files opened in one workspace to be "re-"opened
+ in the other workspace when the other workspace is opened.
+- Pin the Express version which should make installing from npm work again.
+- Propagate signals to code-server in the Docker image which means it should
+ stop more quickly and gracefully.
+- Fix missing argon binaries in the standalone releases on arm machines.
+
+## [4.0.2](https://github.com/coder/code-server/releases/tag/v4.0.2) - 2022-01-27
+
+Code v1.63.0
+
+### Fixed
+
+- Unset the `BROWSER` environment variable. This fixes applications that hard
+ exit when trying to spawn the helper script `BROWSER` points to because the
+ file is missing. While we do include the script now we are leaving the
+ variable omitted because the script does not work yet.
+
+## [4.0.1](https://github.com/coder/code-server/releases/tag/v4.0.1) - 2022-01-04
+
+Code v1.63.0
+
+code-server has been rebased on upstream's newly open-sourced server
+implementation (#4414).
+
+### Changed
+
+- Web socket compression has been made the default (when supported). This means
+ the `--enable` flag will no longer take `permessage-deflate` as an option.
+- The static endpoint can no longer reach outside code-server. However the
+ vscode-remote-resource endpoint still can.
+- OpenVSX has been made the default marketplace.
+- The last opened folder/workspace is no longer stored separately in the
+ settings file (we rely on the already-existing query object instead).
+- The marketplace override environment variables `SERVICE_URL` and `ITEM_URL`
+ have been replaced with a single `EXTENSIONS_GALLERY` variable that
+ corresponds to `extensionsGallery` in Code's `product.json`.
+
+### Added
+
+- `VSCODE_PROXY_URI` env var for use in the terminal and extensions.
+
+### Removed
+
+- Extra extension directories have been removed. The `--extra-extensions-dir`
+ and `--extra-builtin-extensions-dir` flags will no longer be accepted.
+- The `--install-source` flag has been removed.
+
+### Deprecated
+
+- `--link` is now deprecated (#4562).
+
+### Security
+
+- We fixed a XSS vulnerability by escaping HTML from messages in the error page (#4430).
+
+## [3.12.0](https://github.com/coder/code-server/releases/tag/v3.12.0) - 2021-09-15
+
+Code v1.60.0
+
+### Changed
+
+- Upgrade Code to 1.60.0.
+
+### Fixed
+
+- Fix logout when using a base path (#3608).
+
+## [3.11.1](https://github.com/coder/code-server/releases/tag/v3.11.1) - 2021-08-06
+
+Undocumented (see releases page).
+
+## [3.11.0](https://github.com/coder/code-server/releases/tag/v3.11.0) - 2021-06-14
+
+Undocumented (see releases page).
+
+## [3.10.2](https://github.com/coder/code-server/releases/tag/v3.10.2) - 2021-05-21
+
+Code v1.56.1
+
+### Added
+
+- Support `extraInitContainers` in helm chart values (#3393).
+
+### Changed
+
+- Change `extraContainers` to support templating in helm chart (#3393).
+
+### Fixed
+
+- Fix "Open Folder" on welcome page (#3437).
+
+## [3.10.1](https://github.com/coder/code-server/releases/tag/v3.10.1) - 2021-05-17
+
+Code v1.56.1
+
+### Fixed
+
+- Check the logged user instead of $USER (#3330).
+- Fix broken node_modules.asar symlink in npm package (#3355).
+- Update cloud agent to fix version issue (#3342).
+
+### Changed
+
+- Use xdgBasedir.runtime instead of tmp (#3304).
+
+## [3.10.0](https://github.com/coder/code-server/releases/tag/v3.10.0) - 2021-05-10
+
+Code v1.56.0
+
+### Changed
+
+- Update to Code 1.56.0 (#3269).
+- Minor connections refactor (#3178). Improves connection stability.
+- Use ptyHostService (#3308). This brings us closer to upstream Code.
+
+### Added
+
+- Add flag for toggling permessage-deflate (#3286). The default is off so
+ compression will no longer be used by default. Use the --enable flag to
+ toggle it back on.
+
+### Fixed
+
+- Make rate limiter not count against successful logins (#3141).
+- Refactor logout (#3277). This fixes logging out in some scenarios.
+- Make sure directories exist (#3309). This fixes some errors on startup.
+
+### Security
+
+- Update dependencies with CVEs (#3223).
+
+## Previous versions
+
+This was added with `3.10.0`, which means any previous versions are not
+documented in the changelog.
+
+To see those, please visit the [Releases page](https://github.com/coder/code-server/releases).
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index 031b52b67b6d..000000000000
--- a/Dockerfile
+++ /dev/null
@@ -1,60 +0,0 @@
-FROM node:10.16.0
-ARG codeServerVersion=docker
-ARG vscodeVersion
-ARG githubToken
-
-# Install VS Code's deps. These are the only two it seems we need.
-RUN apt-get update && apt-get install -y \
- libxkbfile-dev \
- libsecret-1-dev
-
-# Ensure latest yarn.
-RUN npm install -g yarn@1.13
-
-WORKDIR /src
-COPY . .
-
-RUN yarn \
- && MINIFY=true GITHUB_TOKEN="${githubToken}" yarn build "${vscodeVersion}" "${codeServerVersion}" \
- && yarn binary "${vscodeVersion}" "${codeServerVersion}" \
- && mv "/src/build/code-server${codeServerVersion}-vsc${vscodeVersion}-linux-x86_64-built/code-server${codeServerVersion}-vsc${vscodeVersion}-linux-x86_64" /src/build/code-server \
- && rm -r /src/build/vscode-* \
- && rm -r /src/build/code-server*-linux-*
-
-# We deploy with ubuntu so that devs have a familiar environment.
-FROM ubuntu:18.04
-
-RUN apt-get update && apt-get install -y \
- openssl \
- net-tools \
- git \
- locales \
- sudo \
- dumb-init \
- vim \
- curl \
- wget
-
-RUN locale-gen en_US.UTF-8
-# We cannot use update-locale because docker will not use the env variables
-# configured in /etc/default/locale so we need to set it manually.
-ENV LC_ALL=en_US.UTF-8
-
-RUN adduser --gecos '' --disabled-password coder && \
- echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd
-
-USER coder
-# We create first instead of just using WORKDIR as when WORKDIR creates, the
-# user is root.
-RUN mkdir -p /home/coder/project
-
-WORKDIR /home/coder/project
-
-# This ensures we have a volume mounted even if the user forgot to do bind
-# mount. So that they do not lose their data if they delete the container.
-VOLUME [ "/home/coder/project" ]
-
-COPY --from=0 /src/build/code-server /usr/local/bin/code-server
-EXPOSE 8080
-
-ENTRYPOINT ["dumb-init", "code-server", "--host", "0.0.0.0"]
diff --git a/README.md b/README.md
deleted file mode 100644
index c87fdd2103a2..000000000000
--- a/README.md
+++ /dev/null
@@ -1,166 +0,0 @@
-# code-server · [](https://github.com/cdr/code-server/blob/master/LICENSE) [](https://github.com/cdr/code-server/releases/latest) [](https://github.com/cdr/code-server)
-
-`code-server` is [VS Code](https://github.com/Microsoft/vscode) running on a
-remote server, accessible through the browser.
-
-Try it out:
-
-```bash
-docker run -it -p 127.0.0.1:8080:8080 -v "${HOME}/.local/share/code-server:/home/coder/.local/share/code-server" -v "$PWD:/home/coder/project" codercom/code-server:v2
-```
-
-- **Consistent environment:** Code on your Chromebook, tablet, and laptop with a
- consistent dev environment. develop more easily for Linux if you have a
- Windows or Mac, and pick up where you left off when switching workstations.
-- **Server-powered:** Take advantage of large cloud servers to speed up tests,
- compilations, downloads, and more. Preserve battery life when you're on the go
- since all intensive computation runs on your server.
-
-
-
-## Getting Started
-
-### Requirements
-
-- Minimum GLIBC version of 2.17 and a minimum version of GLIBCXX of 3.4.15.
- - This is the main requirement for building Visual Studio Code. We cannot go lower than this.
-- A 64-bit host with at least 1GB RAM and 2 cores.
- - 1 core hosts would work but not optimally.
-- Docker (for Docker versions of `code-server`).
-
-### Run over SSH
-
-Use [sshcode](https://github.com/codercom/sshcode) for a simple setup.
-
-### Docker
-
-See the Docker one-liner mentioned above. Dockerfile is at [/Dockerfile](/Dockerfile).
-
-To debug Golang using the
-[ms-vscode-go extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.Go),
-you need to add `--security-opt seccomp=unconfined` to your `docker run`
-arguments when launching code-server with Docker. See
-[#725](https://github.com/cdr/code-server/issues/725) for details.
-
-### Digital Ocean
-
-[](https://marketplace.digitalocean.com/apps/code-server?action=deploy)
-
-### Binaries
-
-1. [Download a binary](https://github.com/cdr/code-server/releases). (Linux and
- OS X supported. Windows coming soon)
-2. Unpack the downloaded file then run the binary.
-3. In your browser navigate to `localhost:8080`.
-
-- For self-hosting and other information see [doc/quickstart.md](doc/quickstart.md).
-- For hosting on cloud platforms see [doc/deploy.md](doc/deploy.md).
-
-### Build
-
-- If you also plan on developing, set the `OUT` environment variable. Otherwise
- it will build in this directory which will cause issues because `yarn watch`
- will try to compile the build directory as well.
-- Run `yarn build ${vscodeVersion} ${codeServerVersion}` in this directory (for
- example: `yarn build 1.36.0 development`).
-- If you target the same VS Code version our Travis builds do everything will
- work but if you target some other version it might not (we have to do some
- patching to VS Code so different versions aren't always compatible).
-- You can run the built code with `node path/to/build/out/vs/server/main.js` or run
- `yarn binary` with the same arguments in the previous step to package the
- code into a single binary.
-
-## Known Issues
-
-- Creating custom VS Code extensions and debugging them doesn't work.
-- Extension profiling and tips are currently disabled.
-
-## Future
-
-- **Stay up to date!** Get notified about new releases of code-server.
- 
-- Windows support.
-- Electron and Chrome OS applications to bridge the gap between local<->remote.
-- Run VS Code unit tests against our builds to ensure features work as expected.
-
-## Extensions
-
-code-server does not provide access to the official
-[Visual Studio Marketplace](https://marketplace.visualstudio.com/vscode). Instead,
-Coder has created a custom extension marketplace that we manage for open-source
-extensions. If you want to use an extension with code-server that we do not have
-in our marketplace please look for a release in the extension’s repository,
-contact us to see if we have one in the works or, if you build an extension
-locally from open source, you can copy it to the `extensions` folder. If you
-build one locally from open-source please contribute it to the project and let
-us know so we can give you props! If you have your own custom marketplace, it is
-possible to point code-server to it by setting the `SERVICE_URL` and `ITEM_URL`
-environment variables.
-
-## Telemetry
-
-Use the `--disable-telemetry` flag to completely disable telemetry. We use the
-data collected to improve code-server.
-
-## Contributing
-
-### Development
-
-```shell
-git clone https://github.com/microsoft/vscode
-cd vscode
-git checkout
-git clone https://github.com/cdr/code-server src/vs/server
-cd src/vs/server
-yarn patch:apply
-yarn
-yarn watch
-# Wait for the initial compilation to complete (it will say "Finished compilation").
-# Run the next command in another shell.
-yarn start
-# Visit http://localhost:8080
-```
-
-If you run into issues about a different version of Node being used, try running
-`npm rebuild` in the VS Code directory and ignore the error at the end from
-`vscode-ripgrep`.
-
-### Upgrading VS Code
-
-We patch VS Code to provide and fix some functionality. As the web portion of VS
-Code matures, we'll be able to shrink and maybe even entirely eliminate our
-patch. In the meantime, however, upgrading the VS Code version requires ensuring
-that the patch still applies and has the intended effects.
-
-To generate a new patch, **stage all the changes** you want to be included in
-the patch in the VS Code source, then run `yarn patch:generate` in this
-directory.
-
-Our changes include:
-
-- Change the remote schema to `code-server`.
-- Allow multiple extension directories (both user and built-in).
-- Modify 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).
-- Send client-side telemetry through the server and get the initial log level
- from the server.
-- Add an upload service for use in editor windows and the explorer along with a
- file prefix to ignore for temporary files created during upload.
-- Make changing the display language work.
-- Make hiding or toggling the menu bar possible.
-- Make it possible for us to load code on the client.
-- Modify the build process to include our code.
-
-## License
-
-[MIT](LICENSE)
-
-## Enterprise
-
-Visit [our enterprise page](https://coder.com/enterprise) for more information
-about our enterprise offering.
-
-## Commercialization
-
-If you would like to commercialize code-server, please contact
-contact@coder.com.
diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt
new file mode 100644
index 000000000000..fd6f420e235e
--- /dev/null
+++ b/ThirdPartyNotices.txt
@@ -0,0 +1,22 @@
+code-server
+
+THIRD-PARTY SOFTWARE NOTICES AND INFORMATION
+Do Not Translate or Localize
+
+1. Microsoft/vscode version 1.47.0 (https://github.com/Microsoft/vscode)
+
+%% Microsoft/vscode NOTICES AND INFORMATION BEGIN HERE
+=========================================
+MIT License
+
+
+Copyright (c) 2015 - present Microsoft Corporation
+
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/ci/Caddyfile b/ci/Caddyfile
new file mode 100644
index 000000000000..52e4da6da281
--- /dev/null
+++ b/ci/Caddyfile
@@ -0,0 +1,15 @@
+{
+ admin localhost:4444
+}
+:8000 {
+ @portLocalhost path_regexp port ^/([0-9]+)\/ide
+ handle @portLocalhost {
+ uri strip_prefix {re.port.1}/ide
+ reverse_proxy localhost:{re.port.1}
+ }
+
+ handle {
+ respond "Bad hostname" 400
+ }
+
+}
diff --git a/ci/build/build-code-server.sh b/ci/build/build-code-server.sh
new file mode 100755
index 000000000000..df86f2d97a18
--- /dev/null
+++ b/ci/build/build-code-server.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# Builds code-server into out and the frontend into dist.
+
+main() {
+ cd "$(dirname "${0}")/../.."
+
+ tsc
+
+ # If out/node/entry.js does not already have the shebang,
+ # we make sure to add it and make it executable.
+ if ! grep -q -m1 "^#!/usr/bin/env node" out/node/entry.js; then
+ sed -i.bak "1s;^;#!/usr/bin/env node\n;" out/node/entry.js && rm out/node/entry.js.bak
+ chmod +x out/node/entry.js
+ fi
+}
+
+main "$@"
diff --git a/ci/build/build-lib.sh b/ci/build/build-lib.sh
new file mode 100755
index 000000000000..520276c1bfc3
--- /dev/null
+++ b/ci/build/build-lib.sh
@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+
+# This is a library which contains functions used inside ci/build
+#
+# We separated it into it's own file so that we could easily unit test
+# these functions and helpers.
+
+# On some CPU architectures (notably node/uname "armv7l", default on Raspberry Pis),
+# different package managers have different labels for the same CPU (deb=armhf, rpm=armhfp).
+# This function returns the overriden arch on platforms
+# with alternate labels, or the same arch otherwise.
+get_nfpm_arch() {
+ local PKG_FORMAT="${1:-}"
+ local ARCH="${2:-}"
+
+ case "$ARCH" in
+ armv7l)
+ if [ "$PKG_FORMAT" = "deb" ]; then
+ echo armhf
+ elif [ "$PKG_FORMAT" = "rpm" ]; then
+ echo armhfp
+ fi
+ ;;
+ *)
+ echo "$ARCH"
+ ;;
+ esac
+}
diff --git a/ci/build/build-packages.sh b/ci/build/build-packages.sh
new file mode 100755
index 000000000000..dfd29dba20d3
--- /dev/null
+++ b/ci/build/build-packages.sh
@@ -0,0 +1,65 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# Given a release found in $RELEASE_PATH, generate a deb, rpm, and tarball each
+# named after $ARCH (derived from uname -m but can be overridden for
+# cross-compilation) and $OS (derived from uname and cannot be overridden) and
+# place them in ./release-packages and ./release-gcp.
+
+main() {
+ cd "$(dirname "${0}")/../.."
+ source ./ci/lib.sh
+ source ./ci/build/build-lib.sh
+
+ VERSION=$(jq -r .version "$RELEASE_PATH/package.json")
+ export VERSION # for nfpm to use
+
+ mkdir -p release-packages
+
+ release_archive
+
+ if [[ $OS == "linux" ]]; then
+ release_nfpm
+ fi
+}
+
+release_archive() {
+ local release_name="code-server-$VERSION-$OS-$ARCH"
+ if [[ $OS == "linux" || $OS == "windows" ]]; then
+ tar -czf "release-packages/$release_name.tar.gz" --owner=0 --group=0 --transform "s/^$RELEASE_PATH/$release_name/" "$RELEASE_PATH"
+ else
+ tar -czf "release-packages/$release_name.tar.gz" -s "/^$RELEASE_PATH/$release_name/" "$RELEASE_PATH"
+ fi
+
+ echo "done (release-packages/$release_name)"
+
+ release_gcp
+}
+
+release_gcp() {
+ mkdir -p "release-gcp/$VERSION"
+ cp "release-packages/$release_name.tar.gz" "./release-gcp/$VERSION/$OS-$ARCH.tar.gz"
+ mkdir -p "release-gcp/latest"
+ cp "./release-packages/$release_name.tar.gz" "./release-gcp/latest/$OS-$ARCH.tar.gz"
+}
+
+# Generates deb and rpm packages.
+release_nfpm() {
+ local nfpm_config
+
+ export NFPM_ARCH
+
+ NFPM_ARCH="$(get_nfpm_arch deb "$ARCH")"
+ nfpm_config="$(envsubst < ./ci/build/nfpm.yaml)"
+ echo "Building deb"
+ echo "$nfpm_config" | head --lines=4
+ nfpm pkg -f <(echo "$nfpm_config") --target "release-packages/code-server_${VERSION}_${NFPM_ARCH}.deb"
+
+ NFPM_ARCH="$(get_nfpm_arch rpm "$ARCH")"
+ nfpm_config="$(envsubst < ./ci/build/nfpm.yaml)"
+ echo "Building rpm"
+ echo "$nfpm_config" | head --lines=4
+ nfpm pkg -f <(echo "$nfpm_config") --target "release-packages/code-server-$VERSION-$NFPM_ARCH.rpm"
+}
+
+main "$@"
diff --git a/ci/build/build-release.sh b/ci/build/build-release.sh
new file mode 100755
index 000000000000..0b84dfdcd3f9
--- /dev/null
+++ b/ci/build/build-release.sh
@@ -0,0 +1,187 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# Once both code-server and VS Code have been built, use this script to copy
+# them into a single directory (./release), prepare the package.json and
+# product.json, and add shrinkwraps. This results in a generic NPM package that
+# we can publish to NPM.
+
+# MINIFY controls whether minified VS Code is bundled. It must match the value
+# used when VS Code was built.
+MINIFY="${MINIFY-true}"
+
+# node_modules are not copied by default. Set KEEP_MODULES=1 to copy them.
+# Note these modules will be for the platform that built them, making the result
+# no longer generic (it can still be published though as the modules will be
+# ignored when pushing).
+KEEP_MODULES="${KEEP_MODULES-0}"
+
+main() {
+ cd "$(dirname "${0}")/../.."
+
+ source ./ci/lib.sh
+
+ VSCODE_SRC_PATH="lib/vscode"
+ VSCODE_OUT_PATH="$RELEASE_PATH/lib/vscode"
+
+ create_shrinkwraps
+
+ mkdir -p "$RELEASE_PATH"
+
+ bundle_code_server
+ bundle_vscode
+
+ rsync ./docs/README.md "$RELEASE_PATH"
+ rsync LICENSE "$RELEASE_PATH"
+ rsync ./lib/vscode/ThirdPartyNotices.txt "$RELEASE_PATH"
+
+ if [ "$KEEP_MODULES" = 1 ]; then
+ # Copy the code-server launcher.
+ mkdir -p "$RELEASE_PATH/bin"
+ rsync ./ci/build/code-server.sh "$RELEASE_PATH/bin/code-server"
+ chmod 755 "$RELEASE_PATH/bin/code-server"
+
+ # Windows cannot run the shell launcher, so it gets one of its own.
+ if [ "$OS" = windows ]; then
+ rsync ./ci/build/code-server.cmd "$RELEASE_PATH/bin/code-server.cmd"
+ fi
+
+ # Delete the extra bin scripts.
+ rm "$RELEASE_PATH/lib/vscode/bin/remote-cli/code-darwin.sh"
+ rm "$RELEASE_PATH/lib/vscode/bin/remote-cli/code-linux.sh"
+ rm "$RELEASE_PATH/lib/vscode/bin/helpers/browser-darwin.sh"
+ rm "$RELEASE_PATH/lib/vscode/bin/helpers/browser-linux.sh"
+ if [ "$OS" != windows ] ; then
+ rm "$RELEASE_PATH/lib/vscode/bin/remote-cli/code.cmd"
+ rm "$RELEASE_PATH/lib/vscode/bin/helpers/browser.cmd"
+ fi
+ fi
+}
+
+bundle_code_server() {
+ rsync out "$RELEASE_PATH"
+
+ # For source maps and images.
+ mkdir -p "$RELEASE_PATH/src/browser"
+ rsync src/browser/media/ "$RELEASE_PATH/src/browser/media"
+ mkdir -p "$RELEASE_PATH/src/browser/pages"
+ rsync src/browser/pages/*.html "$RELEASE_PATH/src/browser/pages"
+ rsync src/browser/pages/*.css "$RELEASE_PATH/src/browser/pages"
+ rsync src/browser/robots.txt "$RELEASE_PATH/src/browser"
+
+ # Adds the commit to package.json
+ jq --slurp '(.[0] | del(.scripts,.jest,.devDependencies)) * .[1]' package.json <(
+ cat << EOF
+ {
+ "version": "$(jq -r .codeServerVersion "./lib/vscode-reh-web-$VSCODE_TARGET/product.json")",
+ "commit": "$(git rev-parse HEAD)",
+ "scripts": {
+ "postinstall": "sh ./postinstall.sh"
+ }
+ }
+EOF
+ ) > "$RELEASE_PATH/package.json"
+ mv npm-shrinkwrap.json "$RELEASE_PATH"
+
+ if [ "$KEEP_MODULES" = 1 ]; then
+ local rsync_opts=(-a)
+ if [[ ${DEBUG-} = 1 ]]; then
+ rsync_opts+=(-vh)
+ fi
+ # If we build from source, exclude the prebuilds.
+ if [[ ${npm_config_build_from_source-} = true ]]; then
+ rsync_opts+=(--exclude /argon2/prebuilds)
+ fi
+ rsync "${rsync_opts[@]}" node_modules/ "$RELEASE_PATH/node_modules"
+ # Remove dev dependencies.
+ pushd "$RELEASE_PATH"
+ npm prune --production
+ popd
+ fi
+
+ rsync ci/build/npm-postinstall.sh "$RELEASE_PATH/postinstall.sh"
+}
+
+bundle_vscode() {
+ mkdir -p "$VSCODE_OUT_PATH"
+
+ local rsync_opts=(-a)
+ if [[ ${DEBUG-} = 1 ]]; then
+ rsync_opts+=(-vh)
+ fi
+
+ # Some extensions have a .gitignore which excludes their built source from the
+ # npm package so exclude any .gitignore files.
+ rsync_opts+=(--exclude .gitignore)
+
+ # Exclude Node since we want to place it in a directory above.
+ rsync_opts+=(--exclude /node)
+ rsync_opts+=(--exclude /node.exe)
+
+ # Exclude Node modules. Note that these will already only include production
+ # dependencies, so if we do keep them there is no need to do any
+ # post-processing to remove dev dependencies.
+ if [[ $KEEP_MODULES = 0 ]]; then
+ rsync_opts+=(--exclude node_modules)
+ fi
+
+ rsync "${rsync_opts[@]}" "./lib/vscode-reh-web-$VSCODE_TARGET/" "$VSCODE_OUT_PATH"
+
+ # Copy the Node binary.
+ if [[ $KEEP_MODULES = 1 ]]; then
+ if [ "$OS" = windows ]; then
+ cp "./lib/vscode-reh-web-$VSCODE_TARGET/node.exe" "$RELEASE_PATH/lib"
+ else
+ cp "./lib/vscode-reh-web-$VSCODE_TARGET/node" "$RELEASE_PATH/lib"
+ fi
+ fi
+
+ # Merge the package.json for the web/remote server so we can include
+ # dependencies, since we want to ship this via NPM.
+ # Also override the name to prevent vulnerability scanners from
+ # misidentifying this package as VS Code (see #7071).
+ jq --slurp '.[0] * .[1] | .name = "code-oss"' \
+ "$VSCODE_SRC_PATH/remote/package.json" \
+ "$VSCODE_OUT_PATH/package.json" > "$VSCODE_OUT_PATH/package.json.merged"
+ mv "$VSCODE_OUT_PATH/package.json.merged" "$VSCODE_OUT_PATH/package.json"
+ cp "$VSCODE_SRC_PATH/remote/npm-shrinkwrap.json" "$VSCODE_OUT_PATH/npm-shrinkwrap.json"
+
+ # Include global extension dependencies as well.
+ rsync "$VSCODE_SRC_PATH/extensions/package.json" "$VSCODE_OUT_PATH/extensions/package.json"
+ cp "$VSCODE_SRC_PATH/extensions/npm-shrinkwrap.json" "$VSCODE_OUT_PATH/extensions/npm-shrinkwrap.json"
+ rsync "$VSCODE_SRC_PATH/extensions/postinstall.mjs" "$VSCODE_OUT_PATH/extensions/postinstall.mjs"
+}
+
+create_shrinkwraps() {
+ # package-lock.json files (used to ensure deterministic versions of
+ # dependencies) are not packaged when publishing to the NPM registry.
+ #
+ # To ensure deterministic dependency versions (even when code-server is
+ # installed with NPM), we create an npm-shrinkwrap.json file from the
+ # currently installed node_modules. This ensures the versions used from
+ # development (that the package-lock.json guarantees) are also the ones
+ # installed by end-users. These will include devDependencies, but those will
+ # be ignored when installing globally (for code-server), and because we use
+ # --omit=dev (for VS Code).
+
+ # We first generate the shrinkwrap file for code-server itself - which is the
+ # current directory.
+ cp package-lock.json package-lock.json.temp
+ npm shrinkwrap
+ mv package-lock.json.temp package-lock.json
+
+ # Then the shrinkwrap files for the bundled VS Code.
+ pushd "$VSCODE_SRC_PATH/remote/"
+ cp package-lock.json package-lock.json.temp
+ npm shrinkwrap
+ mv package-lock.json.temp package-lock.json
+ popd
+
+ pushd "$VSCODE_SRC_PATH/extensions/"
+ cp package-lock.json package-lock.json.temp
+ npm shrinkwrap
+ mv package-lock.json.temp package-lock.json
+ popd
+}
+
+main "$@"
diff --git a/ci/build/build-vscode.sh b/ci/build/build-vscode.sh
new file mode 100755
index 000000000000..c38b0ae22acc
--- /dev/null
+++ b/ci/build/build-vscode.sh
@@ -0,0 +1,170 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# Builds vscode into lib/vscode/out-vscode.
+
+# MINIFY controls whether a minified version of vscode is built.
+MINIFY=${MINIFY-true}
+
+fix-bin-script() {
+ local script="lib/vscode-reh-web-$VSCODE_TARGET/bin/$1"
+ sed -i.bak "s/@@VERSION@@/$(vscode_version)/g" "$script"
+ sed -i.bak "s/@@COMMIT@@/$BUILD_SOURCEVERSION/g" "$script"
+ sed -i.bak "s/@@APPNAME@@/code-server/g" "$script"
+
+ # Fix Node path on Darwin and Linux.
+ # We do not want expansion here; this text should make it to the file as-is.
+ # shellcheck disable=SC2016
+ sed -i.bak 's/^ROOT=\(.*\)$/VSROOT=\1\nROOT="$(dirname "$(dirname "$VSROOT")")"/g' "$script"
+ sed -i.bak 's/ROOT\/out/VSROOT\/out/g' "$script"
+ # We do not want expansion here; this text should make it to the file as-is.
+ # shellcheck disable=SC2016
+ sed -i.bak 's/$ROOT\/node/${NODE_EXEC_PATH:-$ROOT\/lib\/node}/g' "$script"
+
+ # Fix Node path on Windows.
+ sed -i.bak 's/^set ROOT_DIR=\(.*\)$/set ROOT_DIR=%~dp0..\\..\\..\\..\r\nset VSROOT_DIR=\1/g' "$script"
+ sed -i.bak 's/%ROOT_DIR%\\out/%VSROOT_DIR%\\out/g' "$script"
+ sed -i.bak 's/%ROOT_DIR%\\node.exe/%ROOT_DIR%\\lib\\node.exe/g' "$script"
+
+ chmod +x "$script"
+ rm "$script.bak"
+}
+
+copy-bin-script() {
+ cp "lib/vscode/resources/server/bin/$1" "lib/vscode-reh-web-$VSCODE_TARGET/bin/$1"
+ fix-bin-script "$1"
+}
+
+main() {
+ cd "$(dirname "${0}")/../.."
+
+ source ./ci/lib.sh
+
+ # Set the commit Code will embed into the product.json. We need to do this
+ # since Code tries to get the commit from the `.git` directory which will fail
+ # as it is a submodule.
+ #
+ # Also, we use code-server's commit rather than VS Code's otherwise it would
+ # not update when only our patch files change, and that will cause caching
+ # issues where the browser keeps using outdated code.
+ export BUILD_SOURCEVERSION
+ BUILD_SOURCEVERSION=$(git rev-parse HEAD)
+
+ pushd lib/vscode
+
+ if [[ ! ${VERSION-} ]]; then
+ echo "VERSION not set. Please set before running this script:"
+ echo "VERSION='0.0.0' npm run build:vscode"
+ exit 1
+ fi
+
+ # Modify the product.json:
+ # - Add the date
+ # - Set the code-server name.
+ # - Add our links
+ # - Enable telemetry (this just makes telemetry available; telemetry can still
+ # be disabled by flag or setting)
+ # - Configure trusted extensions (since some, like github.copilot-chat, never
+ # ask to be trusted and this is the only way to get auth working).
+ # - Make Typescript server plugins run in the workspace. We build the remote
+ # server version, so there is no browser distribution, and this key is not
+ # added automatically.
+ #
+ # This needs to be done before building as Code will read this file and embed
+ # it into the client-side code.
+ git checkout product.json # Reset in case the script exited early.
+ cp product.json product.original.json # Since jq has no inline edit.
+ jq --slurp '.[0] * .[1]' product.original.json <(
+ cat << EOF
+ {
+ "enableTelemetry": true,
+ "quality": "stable",
+ "codeServerVersion": "$VERSION",
+ "nameShort": "code-server",
+ "nameLong": "code-server",
+ "applicationName": "code-server",
+ "dataFolderName": ".code-server",
+ "win32MutexName": "codeserver",
+ "licenseUrl": "https://github.com/coder/code-server/blob/main/LICENSE",
+ "win32DirName": "code-server",
+ "win32NameVersion": "code-server",
+ "win32AppUserModelId": "coder.code-server",
+ "win32ShellNameShort": "c&ode-server",
+ "darwinBundleIdentifier": "com.coder.code.server",
+ "linuxIconName": "com.coder.code.server",
+ "reportIssueUrl": "https://github.com/coder/code-server/issues/new",
+ "documentationUrl": "https://go.microsoft.com/fwlink/?LinkID=533484#vscode",
+ "keyboardShortcutsUrlMac": "https://go.microsoft.com/fwlink/?linkid=832143",
+ "keyboardShortcutsUrlLinux": "https://go.microsoft.com/fwlink/?linkid=832144",
+ "keyboardShortcutsUrlWin": "https://go.microsoft.com/fwlink/?linkid=832145",
+ "introductoryVideosUrl": "https://go.microsoft.com/fwlink/?linkid=832146",
+ "tipsAndTricksUrl": "https://go.microsoft.com/fwlink/?linkid=852118",
+ "newsletterSignupUrl": "https://www.research.net/r/vsc-newsletter",
+ "linkProtectionTrustedDomains": [
+ "https://open-vsx.org"
+ ],
+ "trustedExtensionAuthAccess": [
+ "vscode.git", "vscode.github",
+ "github.vscode-pull-request-github",
+ "github.copilot", "github.copilot-chat"
+ ],
+ "aiConfig": {
+ "ariaKey": "code-server"
+ },
+ "extensionPointExtensionKind": {
+ "typescriptServerPlugins": ["workspace"]
+ }
+ }
+EOF
+ ) > product.json
+
+
+ VSCODE_QUALITY=stable npm run gulp compile-copilot-extension-full-build
+
+ npm run gulp core-ci
+ npm run gulp "vscode-reh-web-$VSCODE_TARGET${MINIFY:+-min}-ci"
+
+ # Reset so if you develop after building you will not be stuck with the wrong
+ # commit (the dev client will use `oss-dev` but the dev server will still use
+ # product.json which will have `stable-$commit`).
+ git checkout product.json
+
+ popd
+
+ pushd "lib/vscode-reh-web-$VSCODE_TARGET"
+ # Make sure Code took the version we set in the environment variable. Not
+ # having a version will break display languages.
+ if ! jq -e .commit product.json; then
+ echo "'commit' is missing from product.json"
+ exit 1
+ fi
+ popd
+
+ # Set vars and fix paths.
+ case $OS in
+ windows)
+ fix-bin-script remote-cli/code-server.cmd
+ fix-bin-script helpers/browser.cmd
+ ;;
+ *)
+ fix-bin-script remote-cli/code-server
+ fix-bin-script helpers/browser.sh
+ ;;
+ esac
+
+ # Include bin scripts for other platforms so we can use the right one in the
+ # NPM post-install.
+
+ # These provide a `code-server` command in the integrated terminal to open
+ # files in the current instance.
+ copy-bin-script remote-cli/code-darwin.sh
+ copy-bin-script remote-cli/code-linux.sh
+ copy-bin-script remote-cli/code.cmd
+
+ # These provide a way for terminal applications to open browser windows.
+ copy-bin-script helpers/browser-darwin.sh
+ copy-bin-script helpers/browser-linux.sh
+ copy-bin-script helpers/browser.cmd
+}
+
+main "$@"
diff --git a/ci/build/clean.sh b/ci/build/clean.sh
new file mode 100755
index 000000000000..9d90836a36f6
--- /dev/null
+++ b/ci/build/clean.sh
@@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+main() {
+ cd "$(dirname "${0}")/../.."
+ source ./ci/lib.sh
+
+ git clean -Xffd
+}
+
+main "$@"
diff --git a/ci/build/code-server-nfpm.sh b/ci/build/code-server-nfpm.sh
new file mode 100755
index 000000000000..e12f493ba92c
--- /dev/null
+++ b/ci/build/code-server-nfpm.sh
@@ -0,0 +1,3 @@
+#!/usr/bin/env sh
+
+exec /usr/lib/code-server/bin/code-server "$@"
diff --git a/ci/build/code-server-user.service b/ci/build/code-server-user.service
new file mode 100644
index 000000000000..a2f48e938e55
--- /dev/null
+++ b/ci/build/code-server-user.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=code-server
+After=network.target
+
+[Service]
+Type=exec
+ExecStart=/usr/bin/code-server
+Restart=always
+
+[Install]
+WantedBy=default.target
diff --git a/ci/build/code-server.cmd b/ci/build/code-server.cmd
new file mode 100644
index 000000000000..1b6a5b2ac1e5
--- /dev/null
+++ b/ci/build/code-server.cmd
@@ -0,0 +1,8 @@
+@echo off
+
+rem This script is intended to be bundled into the standalone releases.
+rem Runs code-server with the bundled node binary.
+
+setlocal
+set "ROOT=%~dp0.."
+"%ROOT%\lib\node.exe" "%ROOT%" %*
diff --git a/ci/build/code-server.sh b/ci/build/code-server.sh
new file mode 100755
index 000000000000..801835ea843b
--- /dev/null
+++ b/ci/build/code-server.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+set -eu
+
+# This script is intended to be bundled into the standalone releases.
+# Runs code-server with the bundled node binary.
+
+_realpath() {
+ # See https://github.com/coder/code-server/issues/1537 on why no realpath or readlink -f.
+
+ script="$1"
+ cd "$(dirname "$script")"
+
+ while [ -L "$(basename "$script")" ]; do
+ script="$(readlink "$(basename "$script")")"
+ cd "$(dirname "$script")"
+ done
+
+ echo "$PWD/$(basename "$script")"
+}
+
+root() {
+ script="$(_realpath "$0")"
+ bin_dir="$(dirname "$script")"
+ dirname "$bin_dir"
+}
+
+ROOT="$(root)"
+exec "$ROOT/lib/node" "$ROOT" "$@"
diff --git a/ci/build/code-server@.service b/ci/build/code-server@.service
new file mode 100644
index 000000000000..bfb62d78dea0
--- /dev/null
+++ b/ci/build/code-server@.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=code-server
+After=network.target
+
+[Service]
+Type=exec
+ExecStart=/usr/bin/code-server
+Restart=always
+User=%i
+
+[Install]
+WantedBy=default.target
diff --git a/ci/build/nfpm.yaml b/ci/build/nfpm.yaml
new file mode 100644
index 000000000000..4b0ee371a2eb
--- /dev/null
+++ b/ci/build/nfpm.yaml
@@ -0,0 +1,25 @@
+name: "code-server"
+arch: "${NFPM_ARCH}"
+platform: "linux"
+version: "v${VERSION}"
+section: "devel"
+priority: "optional"
+maintainer: "Joe Previte "
+description: |
+ Run VS Code in the browser.
+vendor: "Coder"
+homepage: "https://github.com/coder/code-server"
+license: "MIT"
+
+contents:
+ - src: ./ci/build/code-server-nfpm.sh
+ dst: /usr/bin/code-server
+
+ - src: ./ci/build/code-server@.service
+ dst: /usr/lib/systemd/system/code-server@.service
+
+ - src: ./ci/build/code-server-user.service
+ dst: /usr/lib/systemd/user/code-server.service
+
+ - src: ./release/*
+ dst: /usr/lib/code-server
diff --git a/ci/build/npm-postinstall.sh b/ci/build/npm-postinstall.sh
new file mode 100755
index 000000000000..856f1acfa9eb
--- /dev/null
+++ b/ci/build/npm-postinstall.sh
@@ -0,0 +1,134 @@
+#!/usr/bin/env sh
+set -eu
+
+# Copied from ../lib.sh except we do not rename Darwin and we do not need to
+# detect Alpine.
+os() {
+ osname=$(uname | tr '[:upper:]' '[:lower:]')
+ case $osname in
+ cygwin* | mingw*) osname="windows" ;;
+ esac
+ echo "$osname"
+}
+
+# Create a symlink at $2 pointing to $1 on any platform. Anything that
+# currently exists at $2 will be deleted.
+symlink() {
+ source="$1"
+ dest="$2"
+ rm -rf "$dest"
+ case $OS in
+ windows) cmd //c mklink //J "$dest" "$source" ;;
+ *) ln -s "$source" "$dest" ;;
+ esac
+}
+
+# Make a symlink at bin/$1/$3 pointing to the platform-specific version of the
+# script in $2. The extension of the link will be .cmd for Windows otherwise it
+# will be whatever is in $4 (or no extension if $4 is not set).
+symlink_bin_script() {
+ oldpwd="$(pwd)"
+ cd "bin/$1"
+ source="$2"
+ dest="$3"
+ ext="${4-}"
+ case $OS in
+ windows) symlink "$source.cmd" "$dest.cmd" ;;
+ darwin | macos) symlink "$source-darwin.sh" "$dest$ext" ;;
+ *) symlink "$source-linux.sh" "$dest$ext" ;;
+ esac
+ cd "$oldpwd"
+}
+
+command_exists() {
+ if [ ! "$1" ]; then return 1; fi
+ command -v "$@" > /dev/null
+}
+
+is_root() {
+ if command_exists id && [ "$(id -u)" = 0 ]; then
+ return 0
+ fi
+ return 1
+}
+
+OS="$(os)"
+
+main() {
+ # Grabs the major version of node from $npm_config_user_agent which looks like
+ # yarn/1.21.1 npm/? node/v14.2.0 darwin x64
+ major_node_version=$(echo "$npm_config_user_agent" | sed -n 's/.*node\/v\([^.]*\).*/\1/p')
+
+ if [ -n "${FORCE_NODE_VERSION:-}" ]; then
+ echo "WARNING: Overriding required Node.js version to v$FORCE_NODE_VERSION"
+ echo "This could lead to broken functionality, and is unsupported."
+ echo "USE AT YOUR OWN RISK!"
+ fi
+
+ if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-24}" ]; then
+ echo "ERROR: code-server currently requires node v24."
+ if [ -n "${FORCE_NODE_VERSION:-}" ]; then
+ echo "However, you have overrided the version check to use v$FORCE_NODE_VERSION."
+ fi
+ echo "We have detected that you are on node v$major_node_version"
+ echo "You can override this version check by setting \$FORCE_NODE_VERSION,"
+ echo "but configurations that do not use the same node version are unsupported."
+ exit 1
+ fi
+
+
+ if ! vscode_install; then
+ echo "You may not have the required dependencies to build the native modules."
+ echo "Please see https://github.com/coder/code-server/blob/main/docs/npm.md"
+ exit 1
+ fi
+
+ if [ -n "${FORCE_NODE_VERSION:-}" ]; then
+ echo "WARNING: The required Node.js version was overriden to v$FORCE_NODE_VERSION"
+ echo "This could lead to broken functionality, and is unsupported."
+ echo "USE AT YOUR OWN RISK!"
+ fi
+}
+
+install_with_yarn_or_npm() {
+ echo "User agent: ${npm_config_user_agent-none}"
+ # For development we enforce npm, but for installing the package as an
+ # end-user we want to keep using whatever package manager is in use.
+ case "${npm_config_user_agent-}" in
+ npm*)
+ if ! npm install --omit=dev; then
+ return 1
+ fi
+ ;;
+ yarn*)
+ if ! yarn --production --frozen-lockfile --no-default-rc; then
+ return 1
+ fi
+ ;;
+ *)
+ echo "Could not determine which package manager is being used to install code-server"
+ exit 1
+ ;;
+ esac
+ return 0
+}
+
+vscode_install() {
+ echo 'Installing Code dependencies...'
+ cd lib/vscode
+ if ! install_with_yarn_or_npm; then
+ return 1
+ fi
+
+ symlink_bin_script remote-cli code code-server
+ symlink_bin_script helpers browser browser .sh
+
+ cd extensions
+ if ! install_with_yarn_or_npm; then
+ return 1
+ fi
+
+ return 0
+}
+
+main "$@"
diff --git a/ci/build/update-repo.sh b/ci/build/update-repo.sh
new file mode 100755
index 000000000000..0f1924fa91a4
--- /dev/null
+++ b/ci/build/update-repo.sh
@@ -0,0 +1,96 @@
+#!/usr/bin/env bash
+
+set -Eeuo pipefail
+
+# Given versions $1 and $2 figure out the first component that is different
+# (major, minor, patch).
+function find_version_diff() {
+ # shellcheck disable=SC2206
+ local a=( ${1//./ } )
+ # shellcheck disable=SC2206
+ local b=( ${2//./ } )
+
+ if [[ ${a[0]} != "${b[0]}" ]] ; then
+ echo major
+ elif [[ ${a[1]} != "${b[1]}" ]] ; then
+ echo minor
+ else
+ echo patch
+ fi
+}
+
+# Bump $1 by the bump type (major, minor, patch) in $2.
+function bump_version() {
+ # shellcheck disable=SC2206
+ local a=( ${1//./ } )
+ case $2 in
+ major)
+ ((a[0]++))
+ a[1]=0
+ a[2]=0
+ ;;
+ minor)
+ ((a[1]++))
+ a[2]=0
+ ;;
+ *)
+ ((a[2]++))
+ ;;
+ esac
+ echo "${a[0]}.${a[1]}.${a[2]}"
+}
+
+function update_helm() {
+ local chart_version
+ chart_version=$(yq .version ci/helm-chart/Chart.yaml)
+ local app_version
+ app_version=$(yq .appVersion ci/helm-chart/Chart.yaml)
+ local image_version
+ image_version=$(yq .image.tag ci/helm-chart/values.yaml)
+
+ local bump_type
+ bump_type=$(find_version_diff "$app_version" "$version")
+ local chart_version_bump
+ chart_version_bump=$(bump_version "$chart_version" "$bump_type")
+
+ # Use sed to replace because yq will reformat.
+ echo "Bumping version from $chart_version to $chart_version_bump..."
+ sed -i.bak "s/^version: $chart_version\$/version: $chart_version_bump/" ci/helm-chart/Chart.yaml
+
+ echo "Bumping app version from $app_version to $version..."
+ sed -i.bak "s/^appVersion: .\+\$/appVersion: $version/" ci/helm-chart/Chart.yaml
+
+ echo "Bumping image version from $image_version to $version..."
+ sed -i.bak "s/^ tag: .\+\$/ tag: '$version'/" ci/helm-chart/values.yaml
+}
+
+function update_changelog() {
+ local date
+ date=$(printf '%(%Y-%m-%d)T\n' -1)
+ local link="https://github.com/coder/code-server/releases/tag/v$version"
+ sed -i.bak "s|## Unreleased|## Unreleased\n\n## [$version]($link) - $date|" CHANGELOG.md
+}
+
+function main() {
+ cd "$(dirname "${0}")/../.."
+
+ source ./ci/lib.sh
+
+ local version=${VERSION:-$(git describe --tags)}
+ version="${version#v}"
+
+ declare -a steps
+
+ steps+=(
+ "Update Helm chart" "update_helm"
+ "Update changelog" "update_changelog"
+ )
+
+ # Even if a step failed, still output the last checkmark.
+ run-steps "${steps[@]}" || true
+
+ # This step is always manual.
+ echo "- [ ] https://github.com/coder/code-server-aur/pulls" >> .cache/checklist
+}
+
+main "$@"
diff --git a/ci/build/update-vscode.sh b/ci/build/update-vscode.sh
new file mode 100755
index 000000000000..b3b4857d2eb4
--- /dev/null
+++ b/ci/build/update-vscode.sh
@@ -0,0 +1,162 @@
+#!/usr/bin/env bash
+
+set -Eeuo pipefail
+
+function unapply_patches() {
+ local -i exit_code=0
+ quiet quilt pop -af 2>&1 || exit_code=$?
+ case $exit_code in
+ # Sucessfully unapplied.
+ 0) ;;
+ # No more patches to unapply.
+ 2) ;;
+ # Some error.
+ *) return $exit_code ;;
+ esac
+}
+
+function apply_patches() {
+ local -i exit_code=0
+ quiet quilt push -a 2>&1 || exit_code=$?
+ case $exit_code in
+ # Sucessfully applied.
+ 0) ;;
+ # No more patches to apply.
+ 2) ;;
+ # Some error.
+ *) return $exit_code ;;
+ esac
+}
+
+function update_vscode() {
+ pushd lib/vscode
+ if ! git checkout 2>&1 "$target_vscode_version" ; then
+ echo "$target_vscode_version does not exist locally, fetching..."
+ git fetch --all --prune --tags
+ echo "Checking out $target_vscode_version again..."
+ git checkout "$target_vscode_version"
+ fi
+ popd
+}
+
+function refresh_patches() {
+ local -i exit_code=0
+ while quiet quilt push 2>&1 ; ! (( exit_code=$? )) ; do
+ quilt refresh 2>&1
+ done
+ case $exit_code in
+ # No more patches to apply.
+ 2) ;;
+ # Some error.
+ *) return $exit_code ;;
+ esac
+}
+
+function update_node() {
+ local node_version
+ node_version=$(cat .node-version)
+ local target_node_version
+ target_node_version=$(grep target lib/vscode/remote/.npmrc | awk -F= '{print $2}' | tr -d '"')
+ if [[ $node_version == "$target_node_version" ]] ; then
+ echo "Already set to $target_node_version"
+ else
+ echo "Updating from $node_version to $target_node_version..."
+ echo "$target_node_version" > .node-version
+ fi
+}
+
+function get-webview-script-hash() {
+ local html
+ html=$(<"$1")
+ local start_tag='"
+ html=${html##*"$start_tag"}
+ html=${html%%"$end_tag"*}
+ echo -n "$html" | openssl sha256 -binary | openssl base64
+}
+
+function delete_csp() {
+ quilt delete csp-hashes.diff || true
+}
+
+function update_csp() {
+ apply_patches
+
+ local files=(
+ ./lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
+ ./lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
+ )
+
+ quilt new csp-hashes.diff
+
+ local file
+ for file in "${files[@]}" ; do
+ quilt add "$file"
+
+ local hash
+ hash=$(get-webview-script-hash "$file")
+ echo "Calculated hash as $hash"
+ # Use octothorpe as a delimiter since the hash may contain a slash.
+ sed -i.bak "s#'sha256-[^']\+'#'sha256-$hash'#" "$file"
+ done
+
+ quilt refresh
+}
+
+function add_changelog() {
+ local file=CHANGELOG.md
+ if grep --quiet "Code $target_vscode_version" "$file" ; then
+ echo "Changelog for $target_vscode_version already exists"
+ else
+ # TODO: This is not exactly robust. In particular, it needs to handle if
+ # there is already a "changed" section.
+ sed -i.bak "s/## Unreleased/## Unreleased\n\nCode v$target_vscode_version\n\n### Changed\n\n- Update to Code $target_vscode_version/" "$file"
+ fi
+}
+
+function main() {
+ cd "$(dirname "${0}")/../.."
+
+ source ./ci/lib.sh
+
+ declare -a steps
+
+ # Hashes are always regenerated to avoid having to resolve conflicts..
+ steps+=("Revert CSP hashes" "delete_csp")
+
+ # If version is not set, assume we are already at the target version and the
+ # user is just trying to resolve conflics.
+ local target_vscode_version
+ if [[ ${VERSION-} ]] ; then
+ # Removing patches only needs to be done locally; in CI we start from a
+ # fresh clone each time.
+ if [[ ! ${CI-} ]] ; then
+ steps+=("Unapplying patches" "unapply_patches")
+ fi
+ target_vscode_version="${VERSION#v}"
+ steps+=(
+ "Update Code to $target_vscode_version" "update_vscode"
+ "Refresh Code patches" "refresh_patches"
+ )
+ else
+ target_vscode_version="$(git -C lib/vscode describe --tags --exact-match)"
+ echo "Detected Code version $target_vscode_version"
+ fi
+
+ steps+=(
+ "Update Node version" "update_node"
+ "Regenerate CSP hashes" "update_csp"
+ "Add changelog note" "add_changelog"
+ )
+
+ # Even if a step failed, still output the last checkmark.
+ run-steps "${steps[@]}" || true
+
+ # This step is always manual.
+ echo "- [ ] Verify changelog" >> .cache/checklist
+}
+
+main "$@"
diff --git a/ci/dev/doctoc.sh b/ci/dev/doctoc.sh
new file mode 100755
index 000000000000..39930f21e0b5
--- /dev/null
+++ b/ci/dev/doctoc.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+main() {
+ cd "$(dirname "$0")/../.."
+
+ doctoc --title '# FAQ' docs/FAQ.md > /dev/null
+ doctoc --title '# Setup Guide' docs/guide.md > /dev/null
+ doctoc --title '# Install' docs/install.md > /dev/null
+ doctoc --title '# npm Install Requirements' docs/npm.md > /dev/null
+ doctoc --title '# Contributing' docs/CONTRIBUTING.md > /dev/null
+ doctoc --title '# Maintaining' docs/MAINTAINING.md > /dev/null
+ doctoc --title '# Contributor Covenant Code of Conduct' docs/CODE_OF_CONDUCT.md > /dev/null
+ doctoc --title '# iPad' docs/ipad.md > /dev/null
+ doctoc --title '# Termux' docs/termux.md > /dev/null
+
+ if [[ ${CI-} && $(git ls-files --other --modified --exclude-standard) ]]; then
+ echo "Files need generation or are formatted incorrectly:"
+ git -c color.ui=always status | grep --color=no '\[31m'
+ echo "Please run the following locally:"
+ echo " npm run doctoc"
+ exit 1
+ fi
+}
+
+main "$@"
diff --git a/ci/dev/gen_icons.sh b/ci/dev/gen_icons.sh
new file mode 100755
index 000000000000..39d509bc4f4b
--- /dev/null
+++ b/ci/dev/gen_icons.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+set -eu
+
+# Generate icons from a single favicon.svg. favicon.svg should have no fill
+# colors set.
+main() {
+ cd src/browser/media
+
+ # We need .ico for backwards compatibility. The other two are the only icon
+ # sizes required by Chrome and we use them for stuff like apple-touch-icon as
+ # well. https://web.dev/add-manifest/
+ #
+ # This should be enough and we can always add more if there are problems.
+ #
+ # -quiet to avoid https://github.com/ImageMagick/ImageMagick/issues/884
+ # -background defaults to white but we want it transparent.
+ # -density somehow makes the image both sharper and smaller in file size.
+ #
+ # https://imagemagick.org/script/command-line-options.php#background
+ convert -quiet -background transparent \
+ -resize 256x256 -density 256x256 \
+ favicon.svg favicon.ico
+
+ # Generate PWA icons. There should be enough padding to support masking.
+ convert -quiet -border 60x60 -bordercolor white -background white \
+ -resize 192x192 -density 192x192 \
+ favicon.svg pwa-icon-maskable-192.png
+ convert -quiet -border 160x160 -bordercolor white -background white \
+ -resize 512x512 -density 512x512 \
+ favicon.svg pwa-icon-maskable-512.png
+
+ # Generate non-maskable PWA icons.
+ magick pwa-icon-maskable-192.png \
+ \( +clone -threshold 101% -fill white -draw "roundRectangle 0,0 %[fx:int(w)],%[fx:int(h)] 50,50" \) \
+ -channel-fx "| gray=>alpha" \
+ pwa-icon-192.png
+ magick pwa-icon-maskable-512.png \
+ \( +clone -threshold 101% -fill white -draw "roundRectangle 0,0 %[fx:int(w)],%[fx:int(h)] 100,100" \) \
+ -channel-fx "| gray=>alpha" \
+ pwa-icon-512.png
+
+ # The following adds dark mode support for the favicon as
+ # favicon-dark-support.svg There is no similar capability for pwas or .ico so
+ # we can only add support to the svg.
+ favicon_dark_style=""
+ cp favicon.svg favicon-dark-support.svg
+ sed "s% favicon-dark-support.svg
+}
+
+main "$@"
diff --git a/ci/dev/lint-scripts.sh b/ci/dev/lint-scripts.sh
new file mode 100755
index 000000000000..742030affc62
--- /dev/null
+++ b/ci/dev/lint-scripts.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+main() {
+ cd "$(dirname "$0")/../.."
+ shellcheck -e SC2046,SC2164,SC2154,SC1091,SC1090,SC2002 $(git ls-files '*.sh' | grep -v 'lib/vscode')
+}
+
+main "$@"
diff --git a/ci/dev/postinstall.sh b/ci/dev/postinstall.sh
new file mode 100755
index 000000000000..63aad7bcf985
--- /dev/null
+++ b/ci/dev/postinstall.sh
@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# Install dependencies in $1.
+install-deps() {
+ local args=()
+ if [[ ${CI-} ]]; then
+ args+=(ci)
+ else
+ args+=(install)
+ fi
+ # If there is no package.json then npm will look upward and end up installing
+ # from the root resulting in an infinite loop (this can happen if you have not
+ # checked out the submodule yet for example).
+ if [[ ! -f "$1/package.json" ]]; then
+ echo "$1/package.json is missing; did you run git submodule update --init?"
+ exit 1
+ fi
+ pushd "$1"
+ echo "Installing dependencies for $PWD"
+ npm "${args[@]}"
+ popd
+}
+
+main() {
+ cd "$(dirname "$0")/../.."
+ source ./ci/lib.sh
+
+ install-deps test
+ install-deps test/e2e/extensions/test-extension
+ # We don't need these when running the integration tests
+ # so you can pass SKIP_SUBMODULE_DEPS
+ if [[ ! ${SKIP_SUBMODULE_DEPS-} ]]; then
+ install-deps lib/vscode
+ fi
+}
+
+main "$@"
diff --git a/ci/dev/preinstall.js b/ci/dev/preinstall.js
new file mode 100644
index 000000000000..9c4240d89696
--- /dev/null
+++ b/ci/dev/preinstall.js
@@ -0,0 +1,3 @@
+if (process.env.npm_execpath.includes("yarn")) {
+ throw new Error("`yarn` is no longer supported; please use `npm install` instead")
+}
diff --git a/ci/dev/test-e2e.sh b/ci/dev/test-e2e.sh
new file mode 100755
index 000000000000..fa748823974e
--- /dev/null
+++ b/ci/dev/test-e2e.sh
@@ -0,0 +1,50 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+help() {
+ echo >&2 " You can build with 'npm run watch' or you can build a release"
+ echo >&2 " For example: 'npm run build && npm run build:vscode && KEEP_MODULES=1 npm run release'"
+ echo >&2 " Then 'CODE_SERVER_TEST_ENTRY=./release npm run test:e2e'"
+ echo >&2 " You can manually run that release with 'node ./release'"
+}
+
+main() {
+ cd "$(dirname "$0")/../.."
+
+ source ./ci/lib.sh
+
+ pushd test/e2e/extensions/test-extension
+ echo "Building test extension"
+ npm run build
+ popd
+
+ local dir="$PWD"
+ if [[ ! ${CODE_SERVER_TEST_ENTRY-} ]]; then
+ echo "Set CODE_SERVER_TEST_ENTRY to test another build of code-server"
+ else
+ pushd "$CODE_SERVER_TEST_ENTRY"
+ dir="$PWD"
+ popd
+ fi
+
+ echo "Testing build in '$dir'"
+
+ # Simple sanity checks to see that we've built. There could still be things
+ # wrong (native modules version issues, incomplete build, etc).
+ if [[ ! -d $dir/out ]]; then
+ echo >&2 "No code-server build detected"
+ help
+ exit 1
+ fi
+
+ if [[ ! -d $dir/lib/vscode/out ]]; then
+ echo >&2 "No VS Code build detected"
+ help
+ exit 1
+ fi
+
+ cd test
+ ./node_modules/.bin/playwright test "$@"
+}
+
+main "$@"
diff --git a/ci/dev/test-integration.sh b/ci/dev/test-integration.sh
new file mode 100755
index 000000000000..36d87de8ad6d
--- /dev/null
+++ b/ci/dev/test-integration.sh
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+help() {
+ echo >&2 " You can build the release with 'KEEP_MODULES=1 npm run release'"
+ echo >&2 " Or you can pass in a custom path."
+ echo >&2 " CODE_SERVER_PATH='/var/tmp/coder/code-server/bin/code-server' npm run test:integration"
+}
+
+# Make sure a code-server release works. You can pass in the path otherwise it
+# will look for $RELEASE_PATH in the current directory.
+#
+# This is to make sure we don't have Node version errors or any other
+# compilation-related errors.
+main() {
+ cd "$(dirname "$0")/../.."
+
+ source ./ci/lib.sh
+
+ local path="$RELEASE_PATH/bin/code-server"
+ if [[ ! ${CODE_SERVER_PATH-} ]]; then
+ echo "Set CODE_SERVER_PATH to test another build of code-server"
+ else
+ path="$CODE_SERVER_PATH"
+ fi
+
+ echo "Running tests with code-server binary: '$path'"
+
+ if [[ ! -f $path ]]; then
+ echo >&2 "No code-server build detected"
+ echo >&2 "Looked in $path"
+ help
+ exit 1
+ fi
+
+ CODE_SERVER_PATH="$path" ./test/node_modules/.bin/jest "$@" --coverage=false --testRegex "./test/integration" --testPathIgnorePatterns "./test/integration/fixtures"
+}
+
+main "$@"
diff --git a/ci/dev/test-native.sh b/ci/dev/test-native.sh
new file mode 100755
index 000000000000..8e91f9a63e3b
--- /dev/null
+++ b/ci/dev/test-native.sh
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+help() {
+ echo >&2 " You can build the release with 'KEEP_MODULES=1 npm run release'"
+ echo >&2 " Or you can pass in a custom path."
+ echo >&2 " CODE_SERVER_PATH='/var/tmp/coder/code-server/bin/code-server' npm run test:integration"
+}
+
+# Make sure a code-server release works. You can pass in the path otherwise it
+# will look for $RELEASE_PATH in the current directory.
+#
+# This is to make sure we don't have Node version errors or any other
+# compilation-related errors.
+main() {
+ cd "$(dirname "$0")/../.."
+
+ source ./ci/lib.sh
+
+ local path="$RELEASE_PATH/bin/code-server"
+ if [[ ! ${CODE_SERVER_PATH-} ]]; then
+ echo "Set CODE_SERVER_PATH to test another build of code-server"
+ else
+ path="$CODE_SERVER_PATH"
+ fi
+
+ echo "Running tests with code-server binary: '$path'"
+
+ if [[ ! -f $path ]]; then
+ echo >&2 "No code-server build detected"
+ echo >&2 "Looked in $path"
+ help
+ exit 1
+ fi
+
+ CODE_SERVER_PATH="$path" ./test/node_modules/.bin/jest "$@" --coverage=false --testRegex "./test/integration/help.test.ts"
+}
+
+main "$@"
diff --git a/ci/dev/test-scripts.sh b/ci/dev/test-scripts.sh
new file mode 100755
index 000000000000..ebe1efa8ed22
--- /dev/null
+++ b/ci/dev/test-scripts.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+main() {
+ cd "$(dirname "$0")/../.."
+ bats ./test/scripts
+}
+
+main "$@"
diff --git a/ci/dev/test-unit.sh b/ci/dev/test-unit.sh
new file mode 100755
index 000000000000..15fd2030ea59
--- /dev/null
+++ b/ci/dev/test-unit.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+main() {
+ cd "$(dirname "$0")/../.."
+
+ source ./ci/lib.sh
+
+ # We must keep jest in a sub-directory. See ../../test/package.json for more
+ # information. We must also run it from the root otherwise coverage will not
+ # include our source files.
+ ./test/node_modules/.bin/jest "$@" --testRegex "./test/unit/.*ts"
+}
+
+main "$@"
diff --git a/ci/dev/watch.ts b/ci/dev/watch.ts
new file mode 100644
index 000000000000..e48489ce69dc
--- /dev/null
+++ b/ci/dev/watch.ts
@@ -0,0 +1,143 @@
+import { spawn, ChildProcess } from "child_process"
+import * as path from "path"
+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 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 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}`)
+ }
+
+ //#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))
+ }
+
+ for (const [processName, devProcess] of Object.entries(this.compilers)) {
+ if (!devProcess) continue
+
+ 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)
+
+ if (this.compilers.plugins) {
+ onLine(this.compilers.plugins, this.parsePluginLine)
+ }
+ }
+
+ //#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()
+ }
+ }
+
+ 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()
+ }
+ }
+
+ private parsePluginLine: OnLineCallback = (strippedLine, originalLine) => {
+ if (!strippedLine.length) return
+
+ console.log("[Compiler][Plugin]", originalLine)
+
+ if (strippedLine.includes("Watching for file changes...")) {
+ this.reloadWebServer()
+ }
+ }
+
+ //#endregion
+
+ //#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)
+ }
+
+ //#endregion
+}
+
+async function main(): Promise {
+ try {
+ const watcher = new Watcher()
+ await watcher.initialize()
+ } catch (error: any) {
+ console.error(error.message)
+ process.exit(1)
+ }
+}
+
+main()
diff --git a/ci/helm-chart/.helmignore b/ci/helm-chart/.helmignore
new file mode 100644
index 000000000000..0e8a0eb36f4c
--- /dev/null
+++ b/ci/helm-chart/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/ci/helm-chart/Chart.yaml b/ci/helm-chart/Chart.yaml
new file mode 100644
index 000000000000..dd4dec8f4f68
--- /dev/null
+++ b/ci/helm-chart/Chart.yaml
@@ -0,0 +1,23 @@
+apiVersion: v2
+name: code-server
+description: A Helm chart for coder/code-server
+
+# A chart can be either an 'application' or a 'library' chart.
+#
+# Application charts are a collection of templates that can be packaged into versioned archives
+# to be deployed.
+#
+# Library charts provide useful utilities or functions for the chart developer. They're included as
+# a dependency of application charts to inject those utilities and functions into the rendering
+# pipeline. Library charts do not define any templates and therefore cannot be deployed.
+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: 3.56.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: 4.141.0
diff --git a/ci/helm-chart/templates/NOTES.txt b/ci/helm-chart/templates/NOTES.txt
new file mode 100644
index 000000000000..45c9aed3881d
--- /dev/null
+++ b/ci/helm-chart/templates/NOTES.txt
@@ -0,0 +1,24 @@
+1. Get the application URL by running these commands:
+{{- if .Values.ingress.enabled }}
+{{- range $host := .Values.ingress.hosts }}
+ {{- range .paths }}
+ http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ . }}
+ {{- end }}
+{{- end }}
+{{- else if contains "NodePort" .Values.service.type }}
+ export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "code-server.fullname" . }})
+ export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+ echo http://$NODE_IP:$NODE_PORT
+{{- else if contains "LoadBalancer" .Values.service.type }}
+ NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+ You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "code-server.fullname" . }}'
+ 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 }}
+ echo "Visit http://127.0.0.1:8080 to use your application"
+ kubectl port-forward --namespace {{ .Release.Namespace }} service/{{ include "code-server.fullname" . }} 8080:http
+{{- end }}
+
+Administrator credentials:
+
+ Password: echo $(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "code-server.fullname" . }} -o jsonpath="{.data.password}" | base64 --decode)
diff --git a/ci/helm-chart/templates/_helpers.tpl b/ci/helm-chart/templates/_helpers.tpl
new file mode 100644
index 000000000000..bb36e8c21972
--- /dev/null
+++ b/ci/helm-chart/templates/_helpers.tpl
@@ -0,0 +1,63 @@
+{{/* vim: set filetype=mustache: */}}
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "code-server.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "code-server.fullname" -}}
+{{- if .Values.fullnameOverride -}}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
+{{- else -}}
+{{- $name := default .Chart.Name .Values.nameOverride -}}
+{{- if contains $name .Release.Name -}}
+{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
+{{- else -}}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "code-server.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Common labels
+*/}}
+{{- define "code-server.labels" -}}
+helm.sh/chart: {{ include "code-server.chart" . }}
+{{ include "code-server.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "code-server.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "code-server.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "code-server.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create -}}
+ {{ default (include "code-server.fullname" .) .Values.serviceAccount.name }}
+{{- else -}}
+ {{ default "default" .Values.serviceAccount.name }}
+{{- end -}}
+{{- end -}}
diff --git a/ci/helm-chart/templates/deployment.yaml b/ci/helm-chart/templates/deployment.yaml
new file mode 100644
index 000000000000..18bece028fc6
--- /dev/null
+++ b/ci/helm-chart/templates/deployment.yaml
@@ -0,0 +1,194 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ include "code-server.fullname" . }}
+ labels:
+ {{- include "code-server.labels" . | nindent 4 }}
+ {{- if .Values.annotations }}
+ annotations: {{- toYaml .Values.annotations | nindent 4 }}
+ {{- end }}
+spec:
+ {{- if ne .Values.replicaCount nil }}
+ replicas: {{ .Values.replicaCount }}
+ {{- end }}
+ strategy:
+ type: Recreate
+ selector:
+ matchLabels:
+ {{- include "code-server.selectorLabels" . | nindent 6 }}
+ template:
+ metadata:
+ labels:
+ {{- 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 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
+ command:
+ - sh
+ - -c
+ - |
+ chown -R {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} /home/coder
+ securityContext:
+ runAsUser: {{ .Values.volumePermissions.securityContext.runAsUser }}
+ volumeMounts:
+ - name: data
+ mountPath: /home/coder
+ {{- end }}
+{{- if .Values.extraInitContainers }}
+{{ tpl .Values.extraInitContainers . | indent 6}}
+{{- end }}
+ {{- end }}
+ containers:
+{{- if .Values.extraContainers }}
+{{ tpl .Values.extraContainers . | indent 8}}
+{{- end }}
+ - name: {{ .Chart.Name }}
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ {{- if .Values.securityContext.enabled }}
+ 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 }}
+ {{- end }}
+ - name: PASSWORD
+ valueFrom:
+ secretKeyRef:
+ {{- if .Values.existingSecret }}
+ name: {{ .Values.existingSecret }}
+ {{- else }}
+ name: {{ template "code-server.fullname" . }}
+ {{- end }}
+ key: password
+ {{- if .Values.extraArgs }}
+ args:
+{{ toYaml .Values.extraArgs | indent 10 }}
+ {{- end }}
+ volumeMounts:
+ - name: data
+ mountPath: /home/coder
+ {{- range .Values.extraConfigmapMounts }}
+ - name: {{ .name }}
+ mountPath: {{ .mountPath }}
+ subPath: {{ .subPath | default "" }}
+ readOnly: {{ .readOnly }}
+ {{- end }}
+ {{- range .Values.extraSecretMounts }}
+ - name: {{ .name }}
+ mountPath: {{ .mountPath }}
+ subPath: {{ .subPath | default "" }}
+ readOnly: {{ .readOnly }}
+ {{- end }}
+ {{- range .Values.extraVolumeMounts }}
+ - name: {{ .name }}
+ mountPath: {{ .mountPath }}
+ subPath: {{ .subPath | default "" }}
+ readOnly: {{ .readOnly }}
+ {{- end }}
+ ports:
+ - 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: /healthz
+ port: http
+ {{- end }}
+ {{- if ne .Values.readinessProbe.enabled false }}
+ readinessProbe:
+ httpGet:
+ path: /healthz
+ port: http
+ {{- end }}
+ resources:
+ {{- toYaml .Values.resources | nindent 12 }}
+ {{- with .Values.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.affinity }}
+ affinity:
+ {{- tpl . $ | nindent 8 }}
+ {{- end }}
+ {{- with .Values.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ template "code-server.serviceAccountName" . }}
+ volumes:
+ - name: data
+ {{- if .Values.persistence.enabled }}
+ {{- if not .Values.persistence.hostPath }}
+ persistentVolumeClaim:
+ claimName: {{ .Values.persistence.existingClaim | default (include "code-server.fullname" .) }}
+ {{- else }}
+ hostPath:
+ path: {{ .Values.persistence.hostPath }}
+ type: Directory
+ {{- end -}}
+ {{- else }}
+ emptyDir: {}
+ {{- end -}}
+ {{- range .Values.extraSecretMounts }}
+ - name: {{ .name }}
+ secret:
+ 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 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
new file mode 100644
index 000000000000..1da432074b29
--- /dev/null
+++ b/ci/helm-chart/templates/ingress.yaml
@@ -0,0 +1,63 @@
+{{- if .Values.ingress.enabled -}}
+{{- $fullName := include "code-server.fullname" . -}}
+{{- $svcPort := .Values.service.port -}}
+{{- 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
+{{- end }}
+kind: Ingress
+metadata:
+ name: {{ $fullName }}
+ labels:
+ {{- include "code-server.labels" . | nindent 4 }}
+ {{- with .Values.ingress.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ {{- if .Values.ingress.ingressClassName }}
+ ingressClassName: {{ .Values.ingress.ingressClassName }}
+ {{- end }}
+ {{- if .Values.ingress.tls }}
+ tls:
+ {{- range .Values.ingress.tls }}
+ - hosts:
+ {{- range .hosts }}
+ - {{ . | quote }}
+ {{- end }}
+ secretName: {{ .secretName }}
+ {{- 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:
+ paths:
+ {{- range .paths }}
+ - path: {{ . }}
+ backend:
+ serviceName: {{ $fullName }}
+ servicePort: {{ $svcPort }}
+ {{- 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
new file mode 100644
index 000000000000..206b834e930d
--- /dev/null
+++ b/ci/helm-chart/templates/pvc.yaml
@@ -0,0 +1,26 @@
+{{- if and (and .Values.persistence.enabled (not .Values.persistence.existingClaim)) (not .Values.persistence.hostPath) }}
+kind: PersistentVolumeClaim
+apiVersion: v1
+metadata:
+ name: {{ include "code-server.fullname" . }}
+ namespace: {{ .Release.Namespace }}
+{{- with .Values.persistence.annotations }}
+ annotations:
+{{ toYaml . | indent 4 }}
+{{- end }}
+ labels:
+ {{- include "code-server.labels" . | nindent 4 }}
+spec:
+ accessModes:
+ - {{ .Values.persistence.accessMode | quote }}
+ resources:
+ requests:
+ storage: {{ .Values.persistence.size | quote }}
+{{- if .Values.persistence.storageClass }}
+{{- if (eq "-" .Values.persistence.storageClass) }}
+ storageClassName: ""
+{{- else }}
+ storageClassName: "{{ .Values.persistence.storageClass }}"
+{{- end }}
+{{- end }}
+{{- end }}
diff --git a/ci/helm-chart/templates/secrets.yaml b/ci/helm-chart/templates/secrets.yaml
new file mode 100644
index 000000000000..93e75800dffd
--- /dev/null
+++ b/ci/helm-chart/templates/secrets.yaml
@@ -0,0 +1,17 @@
+{{- if not .Values.existingSecret }}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ include "code-server.fullname" . }}
+ annotations:
+ "helm.sh/hook": "pre-install"
+ labels:
+ {{- include "code-server.labels" . | nindent 4 }}
+type: Opaque
+data:
+ {{- if .Values.password }}
+ password: "{{ .Values.password | b64enc }}"
+ {{- else }}
+ password: "{{ randAlphaNum 24 | b64enc }}"
+ {{- end }}
+{{- end }}
diff --git a/ci/helm-chart/templates/service.yaml b/ci/helm-chart/templates/service.yaml
new file mode 100644
index 000000000000..1b58af0b1acd
--- /dev/null
+++ b/ci/helm-chart/templates/service.yaml
@@ -0,0 +1,22 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "code-server.fullname" . }}
+ labels:
+ {{- include "code-server.labels" . | nindent 4 }}
+spec:
+ type: {{ .Values.service.type }}
+ ports:
+ - port: {{ .Values.service.port }}
+ 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
new file mode 100644
index 000000000000..2fa308fec172
--- /dev/null
+++ b/ci/helm-chart/templates/serviceaccount.yaml
@@ -0,0 +1,8 @@
+{{- if or .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ labels:
+ {{- 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
new file mode 100644
index 000000000000..dd81f8904e06
--- /dev/null
+++ b/ci/helm-chart/templates/tests/test-connection.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: "{{ include "code-server.fullname" . }}-test-connection"
+ labels:
+ {{- include "code-server.labels" . | nindent 4 }}
+ annotations:
+ "helm.sh/hook": test
+spec:
+ containers:
+ - name: wget
+ image: busybox
+ command: ['wget']
+ 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
new file mode 100644
index 000000000000..8013333fb083
--- /dev/null
+++ b/ci/helm-chart/values.yaml
@@ -0,0 +1,236 @@
+# Default values for code-server.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+replicaCount: 1
+
+image:
+ repository: codercom/code-server
+ tag: '4.141.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
+ # Annotations to add to the service account
+ annotations: {}
+ # The name of the service account to use.
+ # 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
+
+priorityClassName: ""
+
+service:
+ type: ClusterIP
+ port: 8080
+
+ingress:
+ enabled: false
+ #annotations:
+ # kubernetes.io/tls-acme: "true"
+ #hosts:
+ # - host: code-server.example.loc
+ # paths:
+ # - /
+ ingressClassName: ""
+ #tls:
+ # - secretName: code-server
+ # hosts:
+ # - code-server.example.loc
+
+# Optional additional arguments
+extraArgs: []
+ # 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"
+# if dind is desired:
+# - name: DOCKER_HOST
+# value: "tcp://localhost:2376"
+
+##
+## Init containers parameters:
+## volumePermissions: Change the owner of the persist volume mountpoint to RunAsUser:fsGroup
+##
+volumePermissions:
+ enabled: true
+ securityContext:
+ runAsUser: 0
+
+## Pod Security Context
+## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
+##
+securityContext:
+ enabled: true
+ fsGroup: 1000
+ runAsUser: 1000
+
+resources: {}
+ # We usually recommend not to specify default resources and to leave this as a conscious
+ # choice for the user. This also increases chances charts run on environments with little
+ # resources, such as Minikube. If you do want to specify resources, uncomment the following
+ # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+ # limits:
+ # cpu: 100m
+ # memory: 128Mi
+ # requests:
+ # cpu: 100m
+ # memory: 1000Mi
+
+livenessProbe:
+ enabled: true
+
+readinessProbe:
+ enabled: true
+
+nodeSelector: {}
+
+tolerations: []
+
+affinity: {}
+
+## Persist data to a persistent volume
+persistence:
+ enabled: true
+ ## code-server data Persistent Volume Storage Class
+ ## If defined, storageClassName:
+ ## If set to "-", storageClassName: "", which disables dynamic provisioning
+ ## If undefined (the default) or set to null, no storageClassName spec is
+ ## set, choosing the default provisioner. (gp2 on AWS, standard on
+ ## GKE, AWS & OpenStack)
+ ##
+ # storageClass: "-"
+ accessMode: ReadWriteOnce
+ size: 10Gi
+ annotations: {}
+ # existingClaim: ""
+ # hostPath: /data
+
+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: |
+# 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
+
+## Additional code-server volume mounts
+extraVolumeMounts: []
+ # - name: extra-volume
+ # mountPath: /mnt/volume
+ # readOnly: true
+ # existingClaim: volume-claim
+ # hostPath: ""
+ # emptyDir: {}
+
+extraConfigmapMounts: []
+ # - name: certs-configmap
+ # mountPath: /etc/code-server/ssl/
+ # subPath: certificates.crt # (optional)
+ # configMap: certs-configmap
+ # readOnly: true
+
+extraPorts: []
+ # - name: minecraft
+ # port: 25565
+ # protocol: tcp
diff --git a/ci/lib.sh b/ci/lib.sh
new file mode 100755
index 000000000000..bd9c5c9c0c53
--- /dev/null
+++ b/ci/lib.sh
@@ -0,0 +1,127 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+pushd() {
+ builtin pushd "$@" > /dev/null
+}
+
+popd() {
+ builtin popd > /dev/null
+}
+
+vscode_version() {
+ jq -r .version lib/vscode/package.json
+}
+
+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() {
+ cpu="$(uname -m)"
+ case "$cpu" in
+ aarch64) cpu=arm64 ;;
+ x86_64) cpu=amd64 ;;
+ esac
+ echo "$cpu"
+}
+
+rsync() {
+ command rsync -a --del "$@"
+}
+
+if [[ ! ${ARCH-} ]]; then
+ ARCH=$(arch)
+ export ARCH
+fi
+
+# Windows predefines OS as Windows_NT for every process, so on a windows shell
+# the check below would always find a value and never call os(). That is not a
+# name this build knows, so it does not count as one the caller chose.
+if [[ ! ${OS-} || ${OS-} == "Windows_NT" ]]; then
+ OS=$(os)
+ export OS
+fi
+
+# 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
+
+nodeOS() {
+ osname=$OS
+ case $osname in
+ macos) osname=darwin ;;
+ windows) osname=win32 ;;
+ esac
+ echo "$osname"
+}
+
+nodeArch() {
+ cpu=$ARCH
+ case $cpu in
+ amd64) cpu=x64 ;;
+ esac
+ echo "$cpu"
+}
+
+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
+}
+
+quiet() {
+ "$@" >/dev/null
+}
+
+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
new file mode 100644
index 000000000000..4c91e291e0e8
--- /dev/null
+++ b/ci/release-image/Dockerfile
@@ -0,0 +1,61 @@
+# 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 \
+ curl \
+ dumb-init \
+ git \
+ git-lfs \
+ htop \
+ locales \
+ lsb-release \
+ man-db \
+ nano \
+ openssh-client \
+ procps \
+ sudo \
+ vim-tiny \
+ wget \
+ zsh \
+ && git lfs install \
+ && rm -rf /var/lib/apt/lists/*
+
+# https://wiki.debian.org/Locale#Manually
+RUN sed -i "s/# en_US.UTF-8/en_US.UTF-8/" /etc/locale.gen \
+ && locale-gen
+ENV LANG=en_US.UTF-8
+
+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.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 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
+# 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.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/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
new file mode 100755
index 000000000000..efe2f39d9bd9
--- /dev/null
+++ b/ci/release-image/entrypoint.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 [ -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
+
+# 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 dumb-init /usr/bin/code-server "$@"
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/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/doc/assets/cros.png b/doc/assets/cros.png
deleted file mode 100644
index 64d94c23098d..000000000000
Binary files a/doc/assets/cros.png and /dev/null differ
diff --git a/doc/assets/droplet.svg b/doc/assets/droplet.svg
deleted file mode 100644
index ecbb3f249de1..000000000000
--- a/doc/assets/droplet.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
diff --git a/doc/assets/ide.gif b/doc/assets/ide.gif
deleted file mode 100644
index c8183c1e9fe4..000000000000
Binary files a/doc/assets/ide.gif and /dev/null differ
diff --git a/doc/assets/release.gif b/doc/assets/release.gif
deleted file mode 100644
index b8ad499732b0..000000000000
Binary files a/doc/assets/release.gif and /dev/null differ
diff --git a/doc/cros-install.md b/doc/cros-install.md
deleted file mode 100644
index 0c12b6db5588..000000000000
--- a/doc/cros-install.md
+++ /dev/null
@@ -1,75 +0,0 @@
-# Installing code-server in your ChromiumOS/ChromeOS/CloudReady machine
-
-This guide will show you how to install code-server into your CrOS machine.
-
-## Using Crostini
-
-One of the easier ways to run code-server is via
-[Crostini](https://www.aboutchromebooks.com/tag/project-crostini/), the Linux
-apps support feature in CrOS. Make sure you have enough RAM, HDD space and your
-CPU has VT-x/ AMD-V support. If your chromebook has this, then you are
-qualified to use Crostini.
-
-If you are running R69, you might want to enable this on
-[Chrome Flags](chrome://flags/#enable-experimental-crostini-ui).
-If you run R72, however, this is already enabled for you.
-
-After checking your prerequisites, follow the steps in [the self-host install guide](index.md)
-on installing code-server. Once done, make sure code-server works by running
-it. After running it, simply go to `penguin.linux.test:8080` to access
-code-server. Now you should be greeted with this screen. If you did,
-congratulations, you have installed code-server in your Chromebook!
-
-
-
-Alternatively, if you ran code-server in another container and you need the IP
-for that specific container, simply go to Termina's shell via `crosh` and type
-`vsh termina`.
-
-```bash
-Loading extra module: /usr/share/crosh/dev.d/50-crosh.sh
-Welcome to crosh, the Chrome OS developer shell.
-
-If you got here by mistake, don't panic! Just close this tab and carry on.
-
-Type 'help' for a list of commands.
-
-If you want to customize the look/behavior, you can use the options page.
-Load it by using the Ctrl+Shift+P keyboard shortcut.
-
-crosh> vsh termina
-(termina) chronos@localhost ~ $
-```
-While in termina, run `lxc list`. It should output the list of running containers.
-
-```bash
-(termina) chronos@localhost ~ $ lxc list
-+---------|---------|-----------------------|------|------------|-----------+
-| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
-+---------|---------|-----------------------|------|------------|-----------+
-| penguin | RUNNING | 100.115.92.199 (eth0) | | PERSISTENT | 0 |
-+---------|---------|-----------------------|------|------------|-----------+
-(termina) chronos@localhost ~ $
-```
-
-For this example, we show the default `penguin` container, which is exposed on
-`eth0` at 100.115.92.199. Simply enter the IP of the container where the
-code-server runs to Chrome.
-
-## Using Crouton
-
-[Crouton](https://github.com/dnschneid/crouton) is one of the old ways to get a
-running full Linux via `chroot` on a Chromebook. To use crouton, enable
-developer mode and go to `crosh`. This time, run `shell`, which should drop you
-to `bash`.
-
-Make sure you downloaded `crouton`, if so, go ahead and run it under
-`~/Downloads`. After installing your chroot container via crouton, go ahead and
-enter `enter-chroot` to enter your container.
-
-Follow the instructions set in [the self-host install guide](index.md) to
-install code-server. After that is done, run `code-server` and verify it works
-by going to `localhost:8080`.
-
-> At this point in writing, `localhost` seems to work in this method. However,
-> the author is not sure if it applies still to newer Chromebooks.
diff --git a/doc/deploy.md b/doc/deploy.md
deleted file mode 100644
index f2505e507a8e..000000000000
--- a/doc/deploy.md
+++ /dev/null
@@ -1,73 +0,0 @@
-# Set up instance
-## EC2 on AWS
-- Click **Launch Instance** from your [EC2 dashboard](https://console.aws.amazon.com/ec2/v2/home).
-- Select the Ubuntu Server 18.04 LTS (HVM), SSD Volume Type
-- Select an appropriate instance size (we recommend t2.medium/large, depending
- on team size and number of repositories/languages enabled), then
- **Next: Configure Instance Details**.
-- Select **Next: ...** until you get to the **Configure Security Group** page,
- then add a **Custom TCP Rule** rule with port range set to `8080` and source
- set to "Anywhere".
- > Rules with source of 0.0.0.0/0 allow all IP addresses to access your
- > instance. We recommend setting [security group rules](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-network-security.html?icmpid=docs_ec2_console)
- > to allow access from known IP addresses only.
-- Click **Launch**.
-- You will be prompted to create a key pair.
-- From the dropdown choose "create a new pair", give the key pair a name.
-- Click **Download Key Pair** and store the file in a safe place.
-- Click **Launch Instances**.
-- Head to your [EC2 dashboard](https://console.aws.amazon.com/ec2/v2/home)
- and choose instances from the left panel.
-- In the description of your EC2 instance copy the public DNS (iPv4) address
- using the copy to clipboard button.
-- Open a terminal on your computer and SSH into your instance:
- ```
- ssh -i ${path to key pair} ubuntu@${public address}
- ```
-
-## DigitalOcean
-[Open your DigitalOcean dashboard](https://cloud.digitalocean.com/droplets/new)
-to create a new droplet
-
-- **Choose an image -** Select the **Distributions** tab and then choose Ubuntu.
-- **Choose a size -** We recommend at least 4GB RAM and 2 CPU, more depending
- on team size and number of repositories/languages enabled.
-- Launch your instance.
-- Open a terminal on your computer and SSH into your instance:
- ```
- ssh root@${instance ip}
- ```
-
-## Google Cloud
-> Pre-requisite: Set up the [Google Cloud SDK](https://cloud.google.com/sdk/docs/)
-> on your local machine
-
-- [Open your Google Cloud console](https://console.cloud.google.com/compute/instances)
- to create a new VM instance and click **Create Instance**.
-- Choose an appropriate machine type (we recommend 2 vCPU and 7.5 GB RAM, more
- depending on team size and number of repositories/languages enabled).
-- Choose Ubuntu 16.04 LTS as your boot disk.
-- Expand the "Management, security, disks, networking, sole tenancy" section,
- go to the "Networking" tab, then under network tags add "code-server".
-- Create your VM, and **take note** of its public IP address.
-- Visit "VPC network" in the console and go to "Firewall rules". Create a new
- firewall rule called "http-8080". Under "Target tags" add "code-server", and
- under "Protocols and ports" tick "Specified protocols and ports" and "tcp".
- Beside "tcp", add "8080", then create the rule.
-- Open a terminal on your computer and SSH into your Google Cloud VM:
- ```
- gcloud compute ssh --zone ${region} ${instance name}
- ```
-# Run code-server
-- Download the latest code-server release from the
- [releases page](https://github.com/cdr/code-server/releases/latest)
- to the instance, extract the file, then run the code-server binary:
- ```
- wget https://github.com/cdr/code-server/releases/download/{version}/code-server{version}-linux-x64.tar.gz
- tar -xvzf code-server{version}-linux-x64.tar.gz
- cd code-server{version}-linux-x64
- ./code-server
- ```
-- Open your browser and visit http://$public_ip:8080/ where `$public_ip` is
- your instance's public IP address.
-- For long-term use, set up a systemd service to run code-server.
diff --git a/doc/examples/fail2ban.conf b/doc/examples/fail2ban.conf
deleted file mode 100644
index 2c00872446d5..000000000000
--- a/doc/examples/fail2ban.conf
+++ /dev/null
@@ -1,15 +0,0 @@
-# Fail2Ban filter for code-server
-
-[Definition]
-
-failregex = ^INFO\s+Failed login attempt\s+{\"password\":\"(\\.|[^"])*\",\"remoteAddress\":\"\"
-
-# Use this instead for proxies (ensure the proxy is configured to send the
-# X-Forwarded-For header).
-# failregex = ^INFO\s+Failed login attempt\s+{\"password\":\"(\\.|[^"])*\",\"xForwardedFor\":\"\"
-
-ignoreregex =
-
-datepattern = "timestamp":{EPOCH}}$
-
-# Author: Dean Sheather
diff --git a/doc/examples/kubernetes.aws.yaml b/doc/examples/kubernetes.aws.yaml
deleted file mode 100644
index 079da4b47460..000000000000
--- a/doc/examples/kubernetes.aws.yaml
+++ /dev/null
@@ -1,73 +0,0 @@
-apiVersion: v1
-kind: Namespace
-metadata:
- name: code-server
----
-apiVersion: v1
-kind: Service
-metadata:
- name: code-server
- namespace: code-server
-spec:
- ports:
- - port: 8080
- name: https
- protocol: TCP
- selector:
- app: code-server
- type: ClusterIP
----
-kind: StorageClass
-apiVersion: storage.k8s.io/v1
-metadata:
- name: gp2
- annotations:
- storageclass.kubernetes.io/is-default-class: "true"
-provisioner: kubernetes.io/aws-ebs
-parameters:
- type: gp2
- fsType: ext4
----
-kind: PersistentVolumeClaim
-apiVersion: v1
-metadata:
- name: code-store
- namespace: code-server
-spec:
- accessModes:
- - ReadWriteOnce
- resources:
- requests:
- storage: 60Gi
----
-apiVersion: extensions/v1beta1
-kind: Deployment
-metadata:
- labels:
- app: code-server
- name: code-server
- namespace: code-server
-spec:
- selector:
- matchLabels:
- app: code-server
- replicas: 1
- template:
- metadata:
- labels:
- app: code-server
- spec:
- containers:
- - image: codercom/code-server:v2
- imagePullPolicy: Always
- name: code-servery
- ports:
- - containerPort: 8080
- name: https
- volumeMounts:
- - name: code-server-storage
- mountPath: /go/src
- volumes:
- - name: code-server-storage
- persistentVolumeClaim:
- claimName: code-store
diff --git a/doc/examples/kubernetes.yaml b/doc/examples/kubernetes.yaml
deleted file mode 100644
index 6259689d3283..000000000000
--- a/doc/examples/kubernetes.yaml
+++ /dev/null
@@ -1,43 +0,0 @@
-apiVersion: v1
-kind: Namespace
-metadata:
- name: code-server
----
-apiVersion: v1
-kind: Service
-metadata:
- name: code-server
- namespace: code-server
-spec:
- ports:
- - port: 8080
- name: https
- protocol: TCP
- selector:
- app: code-server
- type: ClusterIP
----
-apiVersion: extensions/v1beta1
-kind: Deployment
-metadata:
- labels:
- app: code-server
- name: code-server
- namespace: code-server
-spec:
- selector:
- matchLabels:
- app: code-server
- replicas: 1
- template:
- metadata:
- labels:
- app: code-server
- spec:
- containers:
- - image: codercom/code-server:v2
- imagePullPolicy: Always
- name: code-server
- ports:
- - containerPort: 8080
- name: https
diff --git a/doc/fail2ban.md b/doc/fail2ban.md
deleted file mode 100644
index 18fbcfee6192..000000000000
--- a/doc/fail2ban.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# Protecting code-server from bruteforce attempts
-code-server outputs all failed login attempts, along with the IP address,
-provided password, user agent and timestamp by default.
-
-When using a reverse proxy such as Nginx or Apache, the remote address may
-appear to be `127.0.0.1` or a similar address so `X-Forwarded-For` should be
-used instead. Ensure that you are setting this value in your reverse proxy:
-
-Nginx:
-```
-location / {
- ...
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- ...
-}
-```
-
-Apache:
-```
-
- ...
- SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded
- ...
-
-```
-
-It is extremely important that you ensure that your code-server instance is not
-accessible from the internet (use localhost or block it in your firewall).
-
-## Fail2Ban
-Fail2Ban allows for automatically banning and logging repeated failed
-authentication attempts for many applications through regex filters. A working
-filter for code-server can be found in `./code-server.fail2ban.conf`. Once this
-is installed and configured correctly, repeated failed login attempts should
-automatically be banned from connecting to your server.
diff --git a/doc/quickstart.md b/doc/quickstart.md
deleted file mode 100644
index db76d15fcafb..000000000000
--- a/doc/quickstart.md
+++ /dev/null
@@ -1,107 +0,0 @@
-# Quickstart Guide
-1. Visit the [releases page](https://github.com/cdr/code-server/releases) and
- download the latest binary for your operating system.
-2. Unpack the downloaded file then run the binary.
-3. In your browser navigate to `localhost:8080`.
-
-## Usage
-Run `code-server --help` to view available options.
-
-### Encrypting traffic with HTTPS
-To encrypt the traffic between the browser and server use `code-server --cert`
-followed by the path to your certificate. Additionally, you can use certificate
-keys with `--cert-key` followed by the path to your key. If you pass `--cert`
-without any path code-server will generate a self-signed certificate.
-
-You can use [Let's Encrypt](https://letsencrypt.org/) to get an SSL certificate
-for free.
-
-### Nginx Reverse Proxy
-The trailing slashes are important.
-
-```
-server {
- listen 80;
- listen [::]:80;
- server_name code.example.com code.example.org;
- location /some/path/ { # Or / if hosting at the root.
- 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;
- }
-}
-```
-
-### Apache Reverse Proxy
-```
-
- ServerName code.example.com
-
- RewriteEngine On
- RewriteCond %{HTTP:Upgrade} =websocket [NC]
- RewriteRule /(.*) ws://localhost:8080/$1 [P,L]
- RewriteCond %{HTTP:Upgrade} !=websocket [NC]
- RewriteRule /(.*) http://localhost:8080/$1 [P,L]
-
- ProxyRequests off
- ProxyPass / http://localhost:8080/ nocanon
- ProxyPassReverse / http://localhost:8080/
-
-```
-
-### Run automatically at startup
-
-In some cases you might need to run code-server automatically once the host starts. You may use your local init service to do so.
-
-#### Systemd
-
-```ini
-[Unit]
-Description=Code Server IDE
-After=network.target
-
-[Service]
-Type=simple
-User=
-EnvironmentFile=$HOME/.profile
-WorkingDirectory=$HOME
-Restart=on-failure
-RestartSec=10
-
-ExecStart= $(pwd)
-
-StandardOutput=file:/var/log/code-server-output.log
-StandardError=file:/var/log/code-server-error.log
-
-[Install]
-WantedBy=multi-user.target
-```
-
-#### OpenRC
-
-```sh
-#!/sbin/openrc-run
-
-depend() {
- after net-online
- need net
-}
-
-supervisor=supervise-daemon
-name="code-server"
-command="/opt/cdr/code-server"
-command_args=""
-
-pidfile="/var/run/cdr.pid"
-respawn_delay=5
-
-set -o allexport
-if [ -f /etc/environment ]; then source /etc/environment; fi
-set +o allexport
-```
-
-#### Kubernetes/Docker
-
-Make sure you set your restart policy to always - this will ensure your container starts as the daemon starts.
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..c492c73b2c59
--- /dev/null
+++ b/docs/FAQ.md
@@ -0,0 +1,601 @@
+
+
+
+# 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)
+- [Can I run code-server with systemd socket activation?](#can-i-run-code-server-with-systemd-socket-activation)
+
+
+
+
+## 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`
+
+## Can I run code-server with systemd socket activation?
+
+Yes. Pass the inherited socket to code-server with `--socket-fd`. systemd
+passes the first listening socket as file descriptor `3`.
+
+Create a socket unit, `~/.config/systemd/user/code-server.socket`:
+
+```ini
+[Socket]
+ListenStream=8080
+
+[Install]
+WantedBy=sockets.target
+```
+
+And a matching service unit, `~/.config/systemd/user/code-server.service`:
+
+```ini
+[Service]
+ExecStart=/usr/bin/code-server --socket-fd 3
+```
+
+Then enable and start the socket:
+
+```bash
+systemctl --user enable --now code-server.socket
+```
+
+code-server will start on the first connection and listen on the socket
+systemd created. `--socket-fd` takes precedence over `--socket` and
+`--bind-addr`/`--port`/`--host`, and `--socket-mode` is ignored because
+systemd owns the socket's permissions.
+
+Socket activation only changes how code-server binds; your usual
+authentication still applies (it keeps prompting for the configured password
+unless you set `--auth none`), so keep authentication enabled when exposing the
+server.
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)
+ - [Cloudflare Rocket Loader](#cloudflare-rocket-loader)
+- [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.
+
+### Cloudflare Rocket Loader
+
+If you serve code-server through Cloudflare, disable Rocket Loader for that
+hostname. Rocket Loader rewrites inline `
+
+
+