Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: coder/envbuilder
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 3759642
Choose a base ref
...
head repository: coder/envbuilder
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: a96ba92
Choose a head ref
  • 13 commits
  • 23 files changed
  • 5 contributors

Commits on Oct 4, 2024

  1. Copy the full SHA
    0096b04 View commit details

Commits on Oct 30, 2024

  1. chore(README.md): add documentation regarding target user (#386)

    (cherry picked from commit d14ab3d)
    johnstcn authored and mafredri committed Oct 30, 2024
    Copy the full SHA
    7756b14 View commit details
  2. chore(envbuilder.go): rename the concept of a magicDir to workingDir (#…

    …388)
    
    (cherry picked from commit aba2f46)
    SasSwart authored and mafredri committed Oct 30, 2024
    Copy the full SHA
    179f3c8 View commit details
  3. feat: add env var for ssh private key (#396)

    (cherry picked from commit 08bdb8d)
    DanielleMaywood authored and mafredri committed Oct 30, 2024
    Copy the full SHA
    b2400e8 View commit details
  4. chore(integration): update TestLogs to validate that CODER_ASGENT_SUB…

    …SYSTEM is set correctly (#397)
    
    (cherry picked from commit 561cc53)
    johnstcn authored and mafredri committed Oct 30, 2024
    Copy the full SHA
    0ab5052 View commit details

Commits on Oct 31, 2024

  1. fix: search $DOCKER_CONFIG if no base64 config is provided (#398)

    (cherry picked from commit c4b082e)
    mafredri committed Oct 31, 2024
    Copy the full SHA
    dc6aa54 View commit details

Commits on Dec 2, 2024

  1. fix: enable logging for setup script when not a tty (#402) (#422)

    Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
    johnstcn and mafredri authored Dec 2, 2024
    Copy the full SHA
    532c639 View commit details
  2. Copy the full SHA
    4cba91f View commit details
  3. feat: allow changing default workspaces folder (#406) (#424)

    (cherry picked from commit 24ef801)
    
    Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
    johnstcn and mafredri authored Dec 2, 2024
    Copy the full SHA
    5b1acda View commit details
  4. fix: update kaniko fork to fix BLOB_UNKNOWN errors (#410) (#425)

    Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
    johnstcn and mafredri authored Dec 2, 2024
    Copy the full SHA
    84e1c40 View commit details
  5. chore: bump github.com/golang-jwt/jwt/v4 from 4.5.0 to 4.5.1 (#405) (#…

    …426)
    
    (cherry picked from commit b1dc272)
    Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    3 people authored Dec 2, 2024
    Copy the full SHA
    0b4600f View commit details
  6. chore: improve logging around lifecycle scripts (#420) (#427)

    (cherry picked from commit fafad44)
    Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    3 people authored Dec 2, 2024
    Copy the full SHA
    15b5420 View commit details
  7. chore: bump golang.org/x/crypto from 0.26.0 to 0.29.0 (#417)

    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    Co-authored-by: Cian Johnston <cian@coder.com>
    (cherry picked from commit a3a6a83)
    dependabot[bot] and johnstcn committed Dec 2, 2024
    Copy the full SHA
    a96ba92 View commit details
11 changes: 9 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -29,6 +29,9 @@ develop:
build: scripts/envbuilder-$(GOARCH)
./scripts/build.sh

.PHONY: gen
gen: docs/env-variables.md update-golden-files

.PHONY: update-golden-files
update-golden-files: .gen-golden

@@ -64,7 +67,7 @@ test-registry-container: .registry-cache

# Pulls images referenced in integration tests and pushes them to the local cache.
.PHONY: test-images-push
test-images-push: .registry-cache/docker/registry/v2/repositories/envbuilder-test-alpine .registry-cache/docker/registry/v2/repositories/envbuilder-test-ubuntu .registry-cache/docker/registry/v2/repositories/envbuilder-test-codercom-code-server
test-images-push: .registry-cache/docker/registry/v2/repositories/envbuilder-test-alpine .registry-cache/docker/registry/v2/repositories/envbuilder-test-ubuntu .registry-cache/docker/registry/v2/repositories/envbuilder-test-codercom-code-server .registry-cache/docker/registry/v2/repositories/envbuilder-test-blob-unknown

.PHONY: test-images-pull
test-images-pull:
@@ -74,6 +77,7 @@ test-images-pull:
docker tag ubuntu:latest localhost:5000/envbuilder-test-ubuntu:latest
docker pull codercom/code-server:latest
docker tag codercom/code-server:latest localhost:5000/envbuilder-test-codercom-code-server:latest
docker build -t localhost:5000/envbuilder-test-blob-unknown:latest -f integration/testdata/blob-unknown/Dockerfile integration/testdata/blob-unknown

.registry-cache:
mkdir -p .registry-cache && chmod -R ag+w .registry-cache
@@ -85,4 +89,7 @@ test-images-pull:
docker push localhost:5000/envbuilder-test-ubuntu:latest

.registry-cache/docker/registry/v2/repositories/envbuilder-test-codercom-code-server:
docker push localhost:5000/envbuilder-test-codercom-code-server:latest
docker push localhost:5000/envbuilder-test-codercom-code-server:latest

.registry-cache/docker/registry/v2/repositories/envbuilder-test-blob-unknown:
docker push localhost:5000/envbuilder-test-blob-unknown:latest
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -48,6 +48,7 @@ To explore more examples, tips, and advanced usage, check out the following guid
- [Git Authentication](./docs/git-auth.md)
- [Caching](./docs/caching.md)
- [Custom Certificates](./docs/custom-certificates.md)
- [Users](./docs/users.md)

## Setup Script

4 changes: 4 additions & 0 deletions cmd/envbuilder/main.go
Original file line number Diff line number Diff line change
@@ -75,6 +75,10 @@ func envbuilderCmd() serpent.Command {
}
}

if o.GitSSHPrivateKeyPath != "" && o.GitSSHPrivateKeyBase64 != "" {
return errors.New("cannot have both GIT_SSH_PRIVATE_KEY_PATH and GIT_SSH_PRIVATE_KEY_BASE64 set")
}

if o.GetCachedImage {
img, err := envbuilder.RunCacheProbe(inv.Context(), o)
if err != nil {
6 changes: 3 additions & 3 deletions devcontainer/devcontainer.go
Original file line number Diff line number Diff line change
@@ -400,11 +400,11 @@ func ImageFromDockerfile(dockerfileContent string) (name.Reference, error) {
arg = strings.TrimSpace(arg)
if strings.Contains(arg, "=") {
parts := strings.SplitN(arg, "=", 2)
key, err := lexer.ProcessWord(parts[0], args)
key, _, err := lexer.ProcessWord(parts[0], shell.EnvsFromSlice(args))
if err != nil {
return nil, fmt.Errorf("processing %q: %w", line, err)
}
val, err := lexer.ProcessWord(parts[1], args)
val, _, err := lexer.ProcessWord(parts[1], shell.EnvsFromSlice(args))
if err != nil {
return nil, fmt.Errorf("processing %q: %w", line, err)
}
@@ -421,7 +421,7 @@ func ImageFromDockerfile(dockerfileContent string) (name.Reference, error) {
if imageRef == "" {
return nil, fmt.Errorf("no FROM directive found")
}
imageRef, err := lexer.ProcessWord(imageRef, args)
imageRef, _, err := lexer.ProcessWord(imageRef, shell.EnvsFromSlice(args))
if err != nil {
return nil, fmt.Errorf("processing %q: %w", imageRef, err)
}
14 changes: 7 additions & 7 deletions devcontainer/devcontainer_test.go
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ import (
"github.com/stretchr/testify/require"
)

const magicDir = "/.envbuilder"
const workingDir = "/.envbuilder"

func stubLookupEnv(string) (string, bool) {
return "", false
@@ -98,7 +98,7 @@ func TestCompileWithFeatures(t *testing.T) {
featureTwoDir := fmt.Sprintf("/.envbuilder/features/two-%x", featureTwoMD5[:4])

t.Run("WithoutBuildContexts", func(t *testing.T) {
params, err := dc.Compile(fs, "", magicDir, "", "", false, stubLookupEnv)
params, err := dc.Compile(fs, "", workingDir, "", "", false, stubLookupEnv)
require.NoError(t, err)

require.Equal(t, `FROM localhost:5000/envbuilder-test-codercom-code-server:latest
@@ -116,7 +116,7 @@ USER 1000`, params.DockerfileContent)
})

t.Run("WithBuildContexts", func(t *testing.T) {
params, err := dc.Compile(fs, "", magicDir, "", "", true, stubLookupEnv)
params, err := dc.Compile(fs, "", workingDir, "", "", true, stubLookupEnv)
require.NoError(t, err)

registryHost := strings.TrimPrefix(registry, "http://")
@@ -155,10 +155,10 @@ func TestCompileDevContainer(t *testing.T) {
dc := &devcontainer.Spec{
Image: "localhost:5000/envbuilder-test-ubuntu:latest",
}
params, err := dc.Compile(fs, "", magicDir, "", "", false, stubLookupEnv)
params, err := dc.Compile(fs, "", workingDir, "", "", false, stubLookupEnv)
require.NoError(t, err)
require.Equal(t, filepath.Join(magicDir, "Dockerfile"), params.DockerfilePath)
require.Equal(t, magicDir, params.BuildContext)
require.Equal(t, filepath.Join(workingDir, "Dockerfile"), params.DockerfilePath)
require.Equal(t, workingDir, params.BuildContext)
})
t.Run("WithBuild", func(t *testing.T) {
t.Parallel()
@@ -181,7 +181,7 @@ func TestCompileDevContainer(t *testing.T) {
_, err = io.WriteString(file, "FROM localhost:5000/envbuilder-test-ubuntu:latest")
require.NoError(t, err)
_ = file.Close()
params, err := dc.Compile(fs, dcDir, magicDir, "", "/var/workspace", false, stubLookupEnv)
params, err := dc.Compile(fs, dcDir, workingDir, "", "/var/workspace", false, stubLookupEnv)
require.NoError(t, err)
require.Equal(t, "ARG1=value1", params.BuildArgs[0])
require.Equal(t, "ARG2=workspace", params.BuildArgs[1])
14 changes: 12 additions & 2 deletions docs/container-registry-auth.md
Original file line number Diff line number Diff line change
@@ -14,9 +14,19 @@ After you have a configuration that resembles the following:
}
```

`base64` encode the JSON and provide it to envbuilder as the `ENVBUILDER_DOCKER_CONFIG_BASE64` environment variable.
`base64` encode the JSON and provide it to envbuilder as the
`ENVBUILDER_DOCKER_CONFIG_BASE64` environment variable.

Alternatively, if running `envbuilder` in Kubernetes, you can create an `ImagePullSecret` and
Alternatively, the configuration file can be placed in `/.envbuilder/config.json`.
The `DOCKER_CONFIG` environment variable can be used to define a custom path. The
path must either be the path to a directory containing `config.json` or the full
path to the JSON file itself.

> [!NOTE] Providing the docker configuration through other means than the
> `ENVBUILDER_DOCKER_CONFIG_BASE64` environment variable will leave the
> configuration file in the container filesystem. This may be a security risk.
When running `envbuilder` in Kubernetes, you can create an `ImagePullSecret` and
pass it into the pod as a volume mount. This example will work for all registries.

```shell
9 changes: 6 additions & 3 deletions docs/env-variables.md
Original file line number Diff line number Diff line change
@@ -15,9 +15,10 @@
| `--dockerfile-path` | `ENVBUILDER_DOCKERFILE_PATH` | | The relative path to the Dockerfile that will be used to build the workspace. This is an alternative to using a devcontainer that some might find simpler. |
| `--build-context-path` | `ENVBUILDER_BUILD_CONTEXT_PATH` | | Can be specified when a DockerfilePath is specified outside the base WorkspaceFolder. This path MUST be relative to the WorkspaceFolder path into which the repo is cloned. |
| `--cache-ttl-days` | `ENVBUILDER_CACHE_TTL_DAYS` | | The number of days to use cached layers before expiring them. Defaults to 7 days. |
| `--docker-config-base64` | `ENVBUILDER_DOCKER_CONFIG_BASE64` | | The base64 encoded Docker config file that will be used to pull images from private container registries. |
| `--docker-config-base64` | `ENVBUILDER_DOCKER_CONFIG_BASE64` | | The base64 encoded Docker config file that will be used to pull images from private container registries. When this is set, Docker configuration set via the DOCKER_CONFIG environment variable is ignored. |
| `--fallback-image` | `ENVBUILDER_FALLBACK_IMAGE` | | Specifies an alternative image to use when neither an image is declared in the devcontainer.json file nor a Dockerfile is present. If there's a build failure (from a faulty Dockerfile) or a misconfiguration, this image will be the substitute. Set ExitOnBuildFailure to true to halt the container if the build faces an issue. |
| `--exit-on-build-failure` | `ENVBUILDER_EXIT_ON_BUILD_FAILURE` | | Terminates the container upon a build failure. This is handy when preferring the FALLBACK_IMAGE in cases where no devcontainer.json or image is provided. However, it ensures that the container stops if the build process encounters an error. |
| `--exit-on-push-failure` | `ENVBUILDER_EXIT_ON_PUSH_FAILURE` | | ExitOnPushFailure terminates the container upon a push failure. This is useful if failure to push the built image should abort execution and result in an error. |
| `--force-safe` | `ENVBUILDER_FORCE_SAFE` | | Ignores any filesystem safety checks. This could cause serious harm to your system! This is used in cases where bypass is needed to unblock customers. |
| `--insecure` | `ENVBUILDER_INSECURE` | | Bypass TLS verification when cloning and pulling from container registries. |
| `--ignore-paths` | `ENVBUILDER_IGNORE_PATHS` | | The comma separated list of paths to ignore when building the workspace. |
@@ -27,9 +28,11 @@
| `--git-clone-single-branch` | `ENVBUILDER_GIT_CLONE_SINGLE_BRANCH` | | Clone only a single branch of the Git repository. |
| `--git-username` | `ENVBUILDER_GIT_USERNAME` | | The username to use for Git authentication. This is optional. |
| `--git-password` | `ENVBUILDER_GIT_PASSWORD` | | The password to use for Git authentication. This is optional. |
| `--git-ssh-private-key-path` | `ENVBUILDER_GIT_SSH_PRIVATE_KEY_PATH` | | Path to an SSH private key to be used for Git authentication. |
| `--git-ssh-private-key-path` | `ENVBUILDER_GIT_SSH_PRIVATE_KEY_PATH` | | Path to an SSH private key to be used for Git authentication. If this is set, then GIT_SSH_PRIVATE_KEY_BASE64 cannot be set. |
| `--git-ssh-private-key-base64` | `ENVBUILDER_GIT_SSH_PRIVATE_KEY_BASE64` | | Base64 encoded SSH private key to be used for Git authentication. If this is set, then GIT_SSH_PRIVATE_KEY_PATH cannot be set. |
| `--git-http-proxy-url` | `ENVBUILDER_GIT_HTTP_PROXY_URL` | | The URL for the HTTP proxy. This is optional. |
| `--workspace-folder` | `ENVBUILDER_WORKSPACE_FOLDER` | | The path to the workspace folder that will be built. This is optional. |
| `--workspace-base-dir` | `ENVBUILDER_WORKSPACE_BASE_DIR` | `/workspaces` | The path under which workspaces will be placed when workspace folder option is not given. |
| `--workspace-folder` | `ENVBUILDER_WORKSPACE_FOLDER` | | The path to the workspace folder that will be built. This is optional. Defaults to `[workspace base dir]/[name]` where name is the name of the repository or `empty`. |
| `--ssl-cert-base64` | `ENVBUILDER_SSL_CERT_BASE64` | | The content of an SSL cert file. This is useful for self-signed certificates. |
| `--export-env-file` | `ENVBUILDER_EXPORT_ENV_FILE` | | Optional file path to a .env file where envbuilder will dump environment variables from devcontainer.json and the built container image. |
| `--post-start-script-path` | `ENVBUILDER_POST_START_SCRIPT_PATH` | | The path to a script that will be created by envbuilder based on the postStartCommand in devcontainer.json, if any is specified (otherwise the script is not created). If this is set, the specified InitCommand should check for the presence of this script and execute it after successful startup. |
9 changes: 9 additions & 0 deletions docs/users.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Root Privileges

Envbuilder always expects to be run as `root` in its container, as building an image will most likely require root privileges. Once the image is built, Envbuilder will drop root privileges and `exec` `ENVBUILDER_INIT_COMMAND` / `ENVBUILDER_INIT_SCRIPT` as a non-root user.

## Choosing a target user

Envbuilder will first attempt to switch to the `containerUser` defined `devcontainer.json`.
If this is not specified, it will look up the last `USER` directive from the specified `Dockerfile` or image.
If no alternative user is specified, Envbuilder will fallback to `root`.
Loading