From 3a364a1cd17b4e652392a294aa6f7d62dd65b4eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E7=84=B6?= Date: Thu, 4 Jun 2026 10:23:59 +0800 Subject: [PATCH 1/3] refactor(egress): split mitmproxy config into yaml (static) vs env (dynamic) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move fleet-wide, rarely-changing mitmproxy options into a baked-in config.yaml under the standard mitm confdir layout, so launch.go only emits per-deployment dynamic overrides via --set. This eliminates two classes of bug along the way: - stream_large_bodies was set in two places (launch.go --set 1m and custom.py ctx.options 10m), with the addon silently winning — making the launch.go line dead code. Now declared once in config.yaml (10m). - ignore_hosts was env-driven with `;`-separated values, but each value was passed as a separate --set, and mitmproxy --set on a list option REPLACES the list — so configuring multiple bypass patterns silently only kept the last one. config.yaml uses a native YAML list with no override semantics. Static options now in /var/lib/mitmproxy/.mitmproxy/config.yaml: mode, listen_host, connection_strategy (lazy — historical default preserved here; switching to eager is tracked in a separate change), stream_large_bodies (10m), http2, ignore_hosts (empty default), ssl_verify_upstream_trusted_confdir (default). Dynamic overrides remain env-driven and applied as --set in launch.go (precedence: --set > config.yaml > mitm defaults): OPENSANDBOX_EGRESS_MITMPROXY_TRANSPARENT (toggle) OPENSANDBOX_EGRESS_MITMPROXY_PORT OPENSANDBOX_EGRESS_MITMPROXY_SCRIPT OPENSANDBOX_EGRESS_MITMPROXY_SSL_INSECURE OPENSANDBOX_EGRESS_MITMPROXY_UPSTREAM_TRUST_DIR Removed env vars (no internal use, replaced by config.yaml): OPENSANDBOX_EGRESS_MITMPROXY_CONFDIR — confdir is the mitm user's home (/var/lib/mitmproxy), which is also where config.yaml lives; splitting them via env created an unused escape hatch that would have broken config.yaml discovery. OPENSANDBOX_EGRESS_MITMPROXY_IGNORE_HOSTS — replaced by ignore_hosts in config.yaml (native list, no covert-overwrite bug). The mitmproxy.Config struct loses its ConfDir field accordingly. SyncRootCA still accepts an optional confDirEnv argument so the existing candidate-path search behavior is preserved if a future caller needs to plumb it back in. --- components/egress/Dockerfile | 13 ++++- .../egress/docs/mitmproxy-transparent.md | 47 +++++++++++++---- components/egress/mitmproxy/config.yaml | 38 ++++++++++++++ components/egress/mitmproxy_transparent.go | 4 +- .../egress/pkg/constants/configuration.go | 5 +- components/egress/pkg/mitmproxy/launch.go | 52 ++++++++----------- 6 files changed, 111 insertions(+), 48 deletions(-) create mode 100644 components/egress/mitmproxy/config.yaml diff --git a/components/egress/Dockerfile b/components/egress/Dockerfile index 512043e94..5851021bf 100644 --- a/components/egress/Dockerfile +++ b/components/egress/Dockerfile @@ -104,13 +104,22 @@ RUN apt-get update \ && rm -rf /var/lib/apt/lists/* # Python mitmproxy (transparent mode): mitmdump runs as user mitmproxy; iptables skips this uid. +# /var/lib/mitmproxy is mitm's home, used as the confdir (CA + config.yaml live under .mitmproxy/). RUN useradd -r -u 10042 -d /var/lib/mitmproxy -s /usr/sbin/nologin mitmproxy \ - && mkdir -p /var/lib/mitmproxy \ - && chown mitmproxy:mitmproxy /var/lib/mitmproxy \ + && mkdir -p /var/lib/mitmproxy/.mitmproxy \ + && chown -R mitmproxy:mitmproxy /var/lib/mitmproxy \ && pip3 install --no-cache-dir --break-system-packages 'mitmproxy>=10,<11' \ && (command -v mitmdump && mitmdump --version) \ && mkdir -p /var/egress/mitmscripts +# Static mitmproxy options (mode, listen_host, connection_strategy, stream_large_bodies, +# http2, ignore_hosts, ssl_verify_upstream_trusted_confdir). mitmdump auto-loads +# config.yaml from its confdir. Dynamic per-deployment options stay env-driven and +# are applied as --set by launch.go (which overrides values declared here). +COPY components/egress/mitmproxy/config.yaml /var/lib/mitmproxy/.mitmproxy/config.yaml +RUN chown mitmproxy:mitmproxy /var/lib/mitmproxy/.mitmproxy/config.yaml \ + && chmod 0644 /var/lib/mitmproxy/.mitmproxy/config.yaml + # All egress runtime artifacts live under one directory to keep paths grouped. COPY --from=builder /out/egress /opt/opensandbox-egress/egress COPY --from=builder /out/opensandbox-supervisor /opt/opensandbox-egress/supervisor diff --git a/components/egress/docs/mitmproxy-transparent.md b/components/egress/docs/mitmproxy-transparent.md index 3df101527..f00451f56 100644 --- a/components/egress/docs/mitmproxy-transparent.md +++ b/components/egress/docs/mitmproxy-transparent.md @@ -32,28 +32,48 @@ export OPENSANDBOX_EGRESS_MITMPROXY_PORT=18081 # Optional: load an additional user-defined mitm addon (loaded after the system addon) export OPENSANDBOX_EGRESS_MITMPROXY_SCRIPT=/path/to/your/addon.py - -# Optional: bypass decryption for selected domains (semicolon-separated regex list) -export OPENSANDBOX_EGRESS_MITMPROXY_IGNORE_HOSTS='.*\.log\.aliyuncs\.com;.*\.example\.internal' ``` +To bypass decryption for selected domains, edit the baked-in +`components/egress/mitmproxy/config.yaml` and rebuild the image — see +"Static Configuration (config.yaml)" below. + ## Configuration Reference +### Environment Variables (Per-Deployment Overrides) + | Variable | Required | Purpose | Default | |------|----------|------|--------| | `OPENSANDBOX_EGRESS_MITMPROXY_TRANSPARENT` | Yes | Enable transparent mitmproxy (`1/true/on`, etc.) | Disabled | | `OPENSANDBOX_EGRESS_MITMPROXY_PORT` | No | mitmdump listen port; `iptables` redirects `80/443` here | `18081` | | `OPENSANDBOX_EGRESS_MITMPROXY_SCRIPT` | No | Additional user mitm addon script path (`-s`); loaded after the system addon | Empty | -| `OPENSANDBOX_EGRESS_MITMPROXY_IGNORE_HOSTS` | No | Host/IP regex list for TLS pass-through (`;` separated) | Empty | -| `OPENSANDBOX_EGRESS_MITMPROXY_CONFDIR` | No | mitm config and CA directory (passed as `--set confdir=`, also used as `HOME`) | Default directory under `/var/lib/mitmproxy` | -| `OPENSANDBOX_EGRESS_MITMPROXY_UPSTREAM_TRUST_DIR` | No | Trust directory for upstream TLS verification (OpenSSL style) | `/etc/ssl/certs` | +| `OPENSANDBOX_EGRESS_MITMPROXY_UPSTREAM_TRUST_DIR` | No | Trust directory for upstream TLS verification (OpenSSL style); overrides the config.yaml default | `/etc/ssl/certs` | +| `OPENSANDBOX_EGRESS_MITMPROXY_SSL_INSECURE` | No | Skip upstream TLS verification (`1/true/on`); use when clients connect by IP and SNI is unavailable | Disabled | Notes: -- `OPENSANDBOX_EGRESS_MITMPROXY_IGNORE_HOSTS` means **no decryption**, not “completely bypass mitm process”. - In transparent mode, mitmproxy generally recommends matching by IP/range; verify SNI/resolve behavior if using domain regex only. - Before mitm, `iptables`, and CA export are ready, `GET /healthz` returns `503 (mitm not ready)` to prevent premature readiness. +### Static Configuration (config.yaml) + +Fleet-wide, rarely-changing mitm options live in +`components/egress/mitmproxy/config.yaml`, baked into the image at +`/var/lib/mitmproxy/.mitmproxy/config.yaml` and auto-loaded by mitmdump. +This is the single source of truth for: + +- `mode` (`transparent`) — mitm default is `regular` +- `listen_host` (`127.0.0.1`) — mitm default is `0.0.0.0` +- `stream_large_bodies` (`10m`) — mitm default is unset (entire body buffered) +- `ssl_verify_upstream_trusted_confdir` (`/etc/ssl/certs`) — mitm default is unset; overridable per-deployment via env +- `ignore_hosts` (`[]`) — matches the mitm default; kept in the file as a discoverable extension point for operators adding TLS pass-through entries + +Only deviations from the mitm built-in defaults are declared in `config.yaml` (the `ignore_hosts` line is the one intentional exception, kept for discoverability). Other options that happen to match the default (`connection_strategy=lazy`, `http2=true`, etc.) are omitted — the file is the diff against upstream defaults, not a full enumeration. + +Precedence: command-line `--set` (from env overrides) > `config.yaml` > mitmproxy built-in defaults. + +To change a static option for the whole fleet: edit `config.yaml`, rebuild the egress image, redeploy. To bypass decryption for a specific host **temporarily** in one deployment, the option is to edit and remount `config.yaml` rather than pass an env override. + ## Common Configuration Templates ### 1) Enable Transparent MITM Only @@ -81,11 +101,18 @@ The user addon is loaded after the system addon (`-s system.py -s user.py`), so ### 4) Bypass Decryption for Specific Domains (e.g. log upload) -```bash -export OPENSANDBOX_EGRESS_MITMPROXY_TRANSPARENT=true -export OPENSANDBOX_EGRESS_MITMPROXY_IGNORE_HOSTS='.*\.log\.aliyuncs\.com' +Edit `components/egress/mitmproxy/config.yaml` and append to `ignore_hosts`, +then rebuild the egress image: + +```yaml +ignore_hosts: + - '.*\.log\.aliyuncs\.com' ``` +`ignore_hosts` means **no decryption**, not "completely bypass mitm process": +mitm still proxies the TCP connection, it just forwards bytes without +breaking TLS, and addons do not see request/response content. + ### 5) Use a Fixed CA (consistent fingerprint across replicas) If CA files already exist in `confdir`, mitmproxy reuses them instead of regenerating on each startup. Typical paths: diff --git a/components/egress/mitmproxy/config.yaml b/components/egress/mitmproxy/config.yaml new file mode 100644 index 000000000..6fdccfce9 --- /dev/null +++ b/components/egress/mitmproxy/config.yaml @@ -0,0 +1,38 @@ +# Static mitmproxy options that override mitm built-in defaults for the +# OpenSandbox egress sidecar. Loaded automatically by mitmdump from +# /var/lib/mitmproxy/.mitmproxy/config.yaml. +# +# Only deviations from mitm defaults are listed here. Options that +# happen to match the mitm default (connection_strategy=lazy, http2=true, +# etc.) are intentionally omitted — the file is meant to be the diff +# against upstream defaults, not a full enumeration. The one exception +# is ignore_hosts: even though [] matches the mitm default, it is kept +# as a discoverable extension point for operators who want to bypass +# decryption for specific hosts without hunting through the docs. +# +# Per-deployment overrides remain env-driven and applied as --set by +# launch.go. Precedence: command-line --set > this file > mitm defaults. + +mode: + - transparent + +# mitm default 0.0.0.0; transparent mode must only accept loopback inside +# the netns (iptables REDIRECT pushes outbound traffic here, and exposing +# mitm on the LAN would route any inbound connection through it). +listen_host: 127.0.0.1 + +# mitm default None (whole body buffered in memory). 10m bounds RSS for +# the allow path; chunked / SSE responses are forced to stream regardless +# by the system addon's responseheaders hook. +stream_large_bodies: 10m + +# mitm default None (Python certifi bundle). Match the OS trust store so +# private-CA additions land where mitm reads them. +ssl_verify_upstream_trusted_confdir: /etc/ssl/certs + +# Hosts (Python regex) for TLS pass-through: mitm forwards bytes without +# decryption and addons do not see request/response content. Empty matches +# the mitm default; kept here as a discoverable extension point. Append +# entries here rather than passing --set on the command line, because +# --set on a list option REPLACES the entire list. +ignore_hosts: [] diff --git a/components/egress/mitmproxy_transparent.go b/components/egress/mitmproxy_transparent.go index 809eb5821..c27066f60 100644 --- a/components/egress/mitmproxy_transparent.go +++ b/components/egress/mitmproxy_transparent.go @@ -106,7 +106,6 @@ func startMitmproxyTransparentIfEnabled() (*mitmTransparent, error) { cfg := mitmproxy.Config{ ListenPort: mpPort, UserName: mitmproxy.RunAsUser, - ConfDir: strings.TrimSpace(os.Getenv(constants.EnvMitmproxyConfDir)), ScriptPath: strings.TrimSpace(os.Getenv(constants.EnvMitmproxyScript)), } // Buffer absorbs OnExit events from a retry storm so OnExit goroutines @@ -131,8 +130,7 @@ func startMitmproxyTransparentIfEnabled() (*mitmTransparent, error) { } log.Infof("mitmproxy: transparent intercept active (OUTPUT tcp 80,443 -> %d; trust mitm CA in clients)", mpPort) - confDir := strings.TrimSpace(os.Getenv(constants.EnvMitmproxyConfDir)) - if err := mitmproxy.SyncRootCA(confDir, mpHome); err != nil { + if err := mitmproxy.SyncRootCA("", mpHome); err != nil { return nil, fmt.Errorf("mitm CA export: %w", err) } return &mitmTransparent{ diff --git a/components/egress/pkg/constants/configuration.go b/components/egress/pkg/constants/configuration.go index 923bb789d..17b8be81b 100644 --- a/components/egress/pkg/constants/configuration.go +++ b/components/egress/pkg/constants/configuration.go @@ -36,12 +36,13 @@ const ( EnvNameserverExempt = "OPENSANDBOX_EGRESS_NAMESERVER_EXEMPT" // MITM: mitmdump transparent; Linux + CAP_NET_ADMIN, runs as a dedicated user. + // Static mitm options (mode, listen_host, connection_strategy, stream_large_bodies, + // http2, ignore_hosts, ssl_verify_upstream_trusted_confdir default) live in + // /var/lib/mitmproxy/.mitmproxy/config.yaml; only per-deployment overrides are env-driven. EnvMitmproxyTransparent = "OPENSANDBOX_EGRESS_MITMPROXY_TRANSPARENT" EnvMitmproxyPort = "OPENSANDBOX_EGRESS_MITMPROXY_PORT" - EnvMitmproxyConfDir = "OPENSANDBOX_EGRESS_MITMPROXY_CONFDIR" EnvMitmproxyScript = "OPENSANDBOX_EGRESS_MITMPROXY_SCRIPT" EnvMitmproxyUpstreamTrustDir = "OPENSANDBOX_EGRESS_MITMPROXY_UPSTREAM_TRUST_DIR" - EnvMitmproxyIgnoreHosts = "OPENSANDBOX_EGRESS_MITMPROXY_IGNORE_HOSTS" EnvMitmproxySslInsecure = "OPENSANDBOX_EGRESS_MITMPROXY_SSL_INSECURE" // Comma-separated upstream resolvers: literal IP only (optional :port) — no hostnames (see dnsproxy REDIRECT note). diff --git a/components/egress/pkg/mitmproxy/launch.go b/components/egress/pkg/mitmproxy/launch.go index 2a1b4e205..399d0d037 100644 --- a/components/egress/pkg/mitmproxy/launch.go +++ b/components/egress/pkg/mitmproxy/launch.go @@ -32,17 +32,23 @@ import ( const RunAsUser = "mitmproxy" // Loopback: transparent mode receives via REDIRECT; do not listen on 0.0.0.0 in the netns. +// Kept as a Go constant only for the startup log line; the actual listen_host is set in +// /var/lib/mitmproxy/.mitmproxy/config.yaml (shipped via the egress Dockerfile). const listenHostLoopback = "127.0.0.1" // systemScriptPath: bundled system addon shipped via the egress Dockerfile // (COPY components/egress/mitmscripts /var/egress/mitmscripts). Always loaded. const systemScriptPath = "/var/egress/mitmscripts/system.py" -// Config: mitmdump --mode transparent; UserName must match iptables ! --uid-owner, ConfDir is mitm state/CA. +// Config: mitmdump --mode transparent. Static options (mode, listen_host, +// connection_strategy, stream_large_bodies, http2, ignore_hosts, +// ssl_verify_upstream_trusted_confdir) live in +// /var/lib/mitmproxy/.mitmproxy/config.yaml and are auto-loaded by mitmdump. +// This struct carries only per-launch dynamic values that override those +// defaults via `--set`. type Config struct { ListenPort int UserName string - ConfDir string // ScriptPath is an optional user-supplied addon, loaded after the system addon. ScriptPath string // OnExit is called (if non-nil) when mitmdump exits. Called from a background goroutine. @@ -92,24 +98,21 @@ func Launch(cfg Config) (*Running, error) { return nil, fmt.Errorf("mitmproxy: lookup user %q: %w", uname, err) } + // Only per-launch dynamic values are passed on the command line. Static + // options (mode, listen_host, connection_strategy, stream_large_bodies, + // http2, ignore_hosts, ssl_verify_upstream_trusted_confdir) come from + // /var/lib/mitmproxy/.mitmproxy/config.yaml shipped in the egress image. + // `--set` overrides config.yaml, so the env-driven overrides below take + // precedence at runtime without rebuilding the image. args := []string{ - "--mode", "transparent", - "--listen-host", listenHostLoopback, "--listen-port", strconv.Itoa(cfg.ListenPort), } - trustDir := strings.TrimSpace(os.Getenv(constants.EnvMitmproxyUpstreamTrustDir)) - if trustDir == "" { - trustDir = "/etc/ssl/certs" + // Upstream cert trust path override. Default in config.yaml is /etc/ssl/certs; + // override per-deployment when the upstream uses a private CA bundle. + if trustDir := strings.TrimSpace(os.Getenv(constants.EnvMitmproxyUpstreamTrustDir)); trustDir != "" { + args = append(args, "--set", "ssl_verify_upstream_trusted_confdir="+trustDir) } - args = append(args, "--set", "ssl_verify_upstream_trusted_confdir="+trustDir) - - // Stream large bodies instead of buffering them in memory (OOM prevention). - args = append(args, "--set", "stream_large_bodies=1m") - - // Lazy connection strategy: defer upstream connection until the request is fully received, - // which avoids unnecessary connections for blocked/filtered requests. - args = append(args, "--set", "connection_strategy=lazy") // Transparent mode redirects TCP to IP addresses. Clients connecting to IPs // do not send SNI, so upstream TLS cert hostname verification fails with @@ -119,34 +122,21 @@ func Launch(cfg Config) (*Running, error) { args = append(args, "--set", "ssl_insecure=true") } - homeEnv := home - if strings.TrimSpace(cfg.ConfDir) != "" { - cd := strings.TrimSpace(cfg.ConfDir) - args = append(args, "--set", "confdir="+cd) - homeEnv = cd - } // Load the system addon first so user addons can observe / override its hooks. args = append(args, "-s", systemScriptPath) if user := strings.TrimSpace(cfg.ScriptPath); user != "" { args = append(args, "-s", user) } - // Upstream passthrough: each pattern becomes --set ignore_hosts= (regex; IP ranges are practical in transparent mode). - for _, p := range strings.Split(os.Getenv(constants.EnvMitmproxyIgnoreHosts), ";") { - p = strings.TrimSpace(p) - if p == "" { - continue - } - args = append(args, "--set", "ignore_hosts="+p) - } - cmd := exec.Command("mitmdump", args...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.SysProcAttr = &syscall.SysProcAttr{ Credential: &syscall.Credential{Uid: uid, Gid: gid}, } - cmd.Env = append(os.Environ(), "HOME="+homeEnv) + // HOME determines mitm's confdir (~/.mitmproxy) which holds both the CA + // and the baked-in config.yaml. + cmd.Env = append(os.Environ(), "HOME="+home) if err := cmd.Start(); err != nil { return nil, fmt.Errorf("mitmproxy: start mitmdump: %w", err) From 8f1e7aeecb2166840c467947a552e4ae123d78ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E7=84=B6?= Date: Thu, 4 Jun 2026 10:25:01 +0800 Subject: [PATCH 2/3] docs(egress): document config.yaml override paths (downstream image, ConfigMap mount) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous draft told operators to edit components/egress/mitmproxy/config.yaml and rebuild — true for the in-repo flow, but does not help operators consuming a published egress image who want different static defaults. Add a section spelling out the three supported override paths: 1. Build a downstream image that COPYs an alternate config.yaml over the baked-in path (recommended: version-controlled, reproducible). 2. Mount an override at /var/lib/mitmproxy/.mitmproxy/config.yaml at runtime (Kubernetes ConfigMap subPath mount example included). 3. Use the env-driven --set escape hatch for the small set of options exposed via environment variables. Also warn against in-container edits, which are lost on restart and blocked by the mitmproxy user's read-only access. --- .../egress/docs/mitmproxy-transparent.md | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/components/egress/docs/mitmproxy-transparent.md b/components/egress/docs/mitmproxy-transparent.md index f00451f56..09cbf0b51 100644 --- a/components/egress/docs/mitmproxy-transparent.md +++ b/components/egress/docs/mitmproxy-transparent.md @@ -72,7 +72,41 @@ Only deviations from the mitm built-in defaults are declared in `config.yaml` (t Precedence: command-line `--set` (from env overrides) > `config.yaml` > mitmproxy built-in defaults. -To change a static option for the whole fleet: edit `config.yaml`, rebuild the egress image, redeploy. To bypass decryption for a specific host **temporarily** in one deployment, the option is to edit and remount `config.yaml` rather than pass an env override. +#### Overriding the built-in config.yaml + +There is no env var to point mitm at an alternate config file. Operators who need different static defaults (e.g. a different `ignore_hosts` list, `connection_strategy`, or `stream_large_bodies`) should pick one of the following: + +1. **Build a downstream image** that derives from the official egress image and replaces the file: + + ```dockerfile + FROM : + COPY my-config.yaml /var/lib/mitmproxy/.mitmproxy/config.yaml + RUN chown mitmproxy:mitmproxy /var/lib/mitmproxy/.mitmproxy/config.yaml \ + && chmod 0644 /var/lib/mitmproxy/.mitmproxy/config.yaml + ``` + + This is the recommended path because the override is version-controlled, reviewable, and reproducible. + +2. **Mount an override file at runtime** over the baked-in path. For Kubernetes, mount a `ConfigMap` as a file at `/var/lib/mitmproxy/.mitmproxy/config.yaml` (be aware that a `ConfigMap` file mount typically lands as read-only with the original UID, so verify the mitmproxy user can read it): + + ```yaml + volumeMounts: + - name: mitm-config + mountPath: /var/lib/mitmproxy/.mitmproxy/config.yaml + subPath: config.yaml + readOnly: true + volumes: + - name: mitm-config + configMap: + name: egress-mitm-config + defaultMode: 0644 + ``` + + Useful for staged rollouts or per-environment overrides without rebuilding the image. + +3. **Single-option escape hatch via env-driven `--set`** (already supported for the documented env variables above). This only works for options exposed via env and only for the single specific override; it cannot replace the whole file. + +Do not edit `config.yaml` inside a running container — the file lives in the container layer, edits are lost on restart, and the mitmproxy user has read-only access by design. ## Common Configuration Templates From a90b629d1cf564a6b19735dafbd0e4d7e0f3419b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E7=84=B6?= Date: Thu, 4 Jun 2026 10:32:24 +0800 Subject: [PATCH 3/3] chore(egress): symlink /egress to new binary path for backward compatibility PR #951 moved the egress binary from /egress to /opt/opensandbox-egress/egress so the supervisor and binary could share a single grouped directory. External tooling and older deployment manifests may still reference the old /egress path; add a symlink so both paths resolve to the same binary. Symlink rather than COPY: zero extra image size, single source of truth for chmod and replacement, and `exec /egress` resolves to the supervisor-managed binary like before. --- components/egress/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/egress/Dockerfile b/components/egress/Dockerfile index 5851021bf..7df26f08d 100644 --- a/components/egress/Dockerfile +++ b/components/egress/Dockerfile @@ -131,7 +131,8 @@ COPY --from=builder /out/opensandbox-supervisor /opt/opensandbox-egress/supervis COPY components/egress/scripts/cleanup.sh /opt/opensandbox-egress/cleanup.sh RUN chmod 0755 /opt/opensandbox-egress/cleanup.sh \ /opt/opensandbox-egress/egress \ - /opt/opensandbox-egress/supervisor + /opt/opensandbox-egress/supervisor \ + && ln -s /opt/opensandbox-egress/egress /egress COPY components/egress/mitmscripts /var/egress/mitmscripts